How to Get the Current Page Slug in WordPress (PHP)

To get the current page slug in WordPress with PHP, use get_post_field( 'post_name', get_the_ID() ). WordPress stores the slug as post_name in the database, and this single function returns it for any post, page, or custom post type:

// Slug of the current post or page
$slug = get_post_field( 'post_name', get_the_ID() );

// Slug of a specific post by ID
$slug = get_post_field( 'post_name', 42 );

echo esc_html( $slug );

Below I’ll cover every common variation: getting a slug from the global $post object, getting the slug from an archive/term page, finding a post by its slug (a different and very common need), getting category or taxonomy slugs, generating slugs programmatically, and ensuring a slug is unique. A WordPress slug is just the URL-friendly version of a title (Hello Worldhello-world), but it shows up in more places than people realize.


Method 1: Get the slug with get_post_field()

This is the cleanest approach. get_post_field() reads straight from the database and works anywhere: inside the loop, inside a custom WP_Query, in an AJAX handler, or in a REST API callback.

// Current post/page
$slug = get_post_field( 'post_name', get_the_ID() );

// Specific post by ID
$slug = get_post_field( 'post_name', 42 );

// Inside a custom loop with WP_Query
while ( $query->have_posts() ) {
    $query->the_post();
    $slug = get_post_field( 'post_name', get_the_ID() );
    echo esc_html( $slug );
}
wp_reset_postdata();

Always esc_html() the output when rendering it on the page. Even though WordPress normalizes slugs to lowercase ASCII, it’s a habit worth keeping for all database-sourced strings.


Method 2: Use the global $post object

Inside the main loop or any template file where the global $post is already set up, you can read the slug off the object directly:

global $post;
$slug = $post->post_name;

echo esc_html( $slug );

It’s fast and readable, but it has one catch: the global $post isn’t always set (AJAX calls, admin pages, custom WP_Query loops without wp_reset_postdata). When in doubt, fall back to Method 1.


Method 3: Get the slug from the queried object

get_queried_object() returns whatever WordPress is currently rendering (a post, a term, a user, a post type archive). It’s the most universal way to get the current slug because it works on both single posts and archive pages:

$queried = get_queried_object();

if ( is_singular() ) {
    // Single post/page/CPT
    $slug = $queried->post_name;
} elseif ( is_category() || is_tag() || is_tax() ) {
    // Taxonomy term archive
    $slug = $queried->slug;
} elseif ( is_post_type_archive() ) {
    // Custom post type archive
    $slug = $queried->rewrite['slug'] ?? $queried->name;
}

Reach for this when you need one snippet that handles every page type your theme renders.


Method 4: Get the slug of the parent page

For hierarchical content (pages with a parent, or custom post types with hierarchical => true), you often want the parent’s slug, not the current page’s:

$parent_id = wp_get_post_parent_id( get_the_ID() );

if ( $parent_id ) {
    $parent_slug = get_post_field( 'post_name', $parent_id );
} else {
    $parent_slug = null;  // this is a top-level page
}

Useful for conditional sidebars, breadcrumb templates, or adding a CSS class that reflects the section a page belongs to.


Method 5: Get a post BY its slug

This is the reverse direction: you have a slug string and need the actual post object (or ID, title, content). Use get_page_by_path(). Despite the name, it works for posts, pages, and any custom post type.

// Get a page by slug (default post type is 'page')
$page = get_page_by_path( 'about-us' );

// Get a post by slug
$post = get_page_by_path( 'my-post-slug', OBJECT, 'post' );

// Get a custom post type by slug
$product = get_page_by_path( 'blue-widget', OBJECT, 'product' );

// Just the ID
$post = get_page_by_path( 'my-post-slug', OBJECT, 'post' );
$post_id = $post ? $post->ID : 0;

The third argument can also be an array of post types (array( 'post', 'page' )) if you want to search across multiple at once. Always check the return value for null before using it, since an invalid slug returns null rather than an error.


Method 6: Get a category, tag, or taxonomy slug

Term objects (categories, tags, custom taxonomies) store their slug in the slug property:

// Get a category slug by ID
$category = get_term( 5, 'category' );
$slug = $category->slug;

// Current category slug on an archive page
$queried = get_queried_object();
$slug = $queried->slug;

// All categories a post belongs to
$categories = get_the_category();
foreach ( $categories as $cat ) {
    echo esc_html( $cat->slug );
}

// All tags a post belongs to
$tags = get_the_tags();
foreach ( $tags as $tag ) {
    echo esc_html( $tag->slug );
}

For custom taxonomies, swap get_the_category() / get_the_tags() for get_the_terms( $post_id, 'your_taxonomy' ).


Method 7: Generate a slug from a string

Building custom URLs, inserting posts programmatically, or creating unique IDs from user input? sanitize_title() is the same function WordPress uses internally when it generates a slug from a post title:

$slug = sanitize_title( 'My Blog Post Title!' );
// Returns: my-blog-post-title

$slug = sanitize_title( 'Déjà vu & other words' );
// Returns: deja-vu-other-words

It lowercases, transliterates accented characters, replaces whitespace with hyphens, and strips characters that aren’t URL-safe.

If the slug is going into a database query (for example, matching against post_name), use sanitize_title_for_query() instead. It’s slightly more aggressive about character handling to guarantee the result matches what WordPress stores.


Method 8: Make sure a generated slug is unique

If you’re programmatically inserting posts (via wp_insert_post() or a custom import), WordPress handles slug uniqueness automatically. If you need the unique slug in advance (for example, to display a preview URL before saving), use wp_unique_post_slug():

$desired_slug = sanitize_title( $user_input_title );

$unique_slug = wp_unique_post_slug(
    $desired_slug,
    0,                    // post ID (0 for new posts)
    'publish',            // post status
    'post',               // post type
    0                     // parent ID
);

// Returns 'my-title' or 'my-title-2' if 'my-title' is already taken

Frequently asked questions

How do I get the current page slug in WordPress?

Use get_post_field( 'post_name', get_the_ID() ). WordPress stores the slug in the post_name database column, and this one line works for posts, pages, and custom post types. Inside the loop, you can also read it from the global $post object as $post->post_name.

How do I get a post by its slug in WordPress?

Use get_page_by_path( 'your-slug', OBJECT, 'post' ). Despite the name, it works for posts, pages, and custom post types. The third argument is the post type (or an array of post types). Check the return value for null before using it, since an invalid slug returns null.

What is the difference between post_name and post_title?

post_title is the human-readable title you see in the admin (“My Blog Post”). post_name is the URL-friendly slug WordPress generates from it (“my-blog-post”). Both live in the wp_posts table. Use get_the_title() for the title and get_post_field( 'post_name', $id ) for the slug.

How do I get the current category slug in WordPress?

On a category archive page, use get_queried_object()->slug. For a specific category by ID, use get_term( $id, 'category' )->slug. For all categories attached to a post, loop through get_the_category() and read each term’s slug property.

How do I generate a WordPress slug from a string?

Use sanitize_title( 'Your String Here' ). It’s the same function WordPress uses internally: it lowercases, transliterates accented characters, replaces spaces with hyphens, and strips characters that aren’t URL-safe. For query matching, use sanitize_title_for_query() to guarantee the result matches what’s stored in the database.

How do I get the slug of the parent page in WordPress?

Combine wp_get_post_parent_id() with get_post_field(): $parent_id = wp_get_post_parent_id( get_the_ID() ); $parent_slug = get_post_field( 'post_name', $parent_id );. If the page is top-level, wp_get_post_parent_id() returns 0, so check that before using the slug.

Why is $post->post_name empty in my code?

Usually because the global $post isn’t set in the context you’re running. This happens in AJAX callbacks, REST API routes, and custom WP_Query loops without wp_reset_postdata(). Fall back to get_post_field( 'post_name', $id ), which doesn’t depend on the global state.


Bottom line

For the current page’s slug, get_post_field( 'post_name', get_the_ID() ) is the one-liner to memorize. For anything that isn’t a singular post (archives, term pages, CPT archives), use get_queried_object() and read the appropriate property. To go the other direction (slug → post), get_page_by_path() handles all post types. And to generate a slug from a string, sanitize_title() matches WordPress’s own behavior.

Related: how to get a post ID, get the post title, get the current URL, or browse the full WordPress code snippets library.

Picture of Andy Feliciotti

Andy Feliciotti

Andy has been a full time WordPress developer for over 15 years. Through his years of experience has built 100s of sites and learned plenty of tricks along the way. Found this article helpful? Buy Me A Coffee

6 Responses

  1. Great post! I appreciate how clearly you explained the difference between get_post_field() and using the global $post object to get the slug. The examples were super helpful especially the one showing how to get the slug by post ID. This will definitely come in handy for some custom functionality I'm building in a theme. Looking forward to more WordPress development tips!

Leave a Reply

Your email address will not be published. Required fields are marked *

WordPress Tips Monthly
Get the latest from SmartWP to your inbox.