Remove The Slugs from Custom Post Type URL

If you are a WordPress user and want to customize the permalink for custom post type to remove the generated slug by WordPress (post_name value) for your custom post type, then you might stumbled across different solution on the web trying something that might achieve the same effect without any performance impact. This method is worth to try. Note: This is a version we found useful and it worked for a particular case. It may not work for you, but you can post a comment below and maybe we can figure it out. So, let us get down to the nitty-gritty. All you need are the following lines of code, that should be placed in your theme’s functions.php file, and your permalink structure should be /%postname%/. First, register your own custom post type normally.

 * Register a custom post type
$args = array(
    'description' => 'Photograph Post Type',
    'label' => __('Photographs'),
    'public' => true,
    'rewrite' => array( 'slug' => 'photograph'),
register_post_type( 'photograph' , $args );

Then the second thing that we have to do is to remove the actual slug from the actual URL, we want to filter the permalink for our custom post type (in this case is “photograph”) such that all published posts don’t have the slug in the URI. We can do this by checking the post type and if the current post has the desired type we proceed in removing the slug using str_replace on the permalink. In order for this function to work we need it to be attach to a hook. Luckily, WordPress has a filter called post_type_link that is used.

 * Remove the slug from published post permalinks.
function custom_remove_cpt_slug( $post_link, $post, $leavename ) {

    if ( 'photograph' != $post->post_type || 'publish' != $post->post_status ) {
        return $post_link;

    $post_link = str_replace( '/' . $post->post_type . '/', '/', $post_link );

    return $post_link;
add_filter( 'post_type_link', 'custom_remove_cpt_slug', 10, 3 );

Now you managed to get until this step but you will hit a 404 if you try to view the link. Well that is because WordPress doesn’t recognize that post as a custom post type anymore. We need to fix and trick WordPress to think that the requested post is in fact a custom post type. Here is the way to do it:

 * Some hackery to have WordPress match postname to any of our public post types
 * All of our public post types can have /post-name/ as the slug, so they better be unique across all posts
 * Typically core only accounts for posts and pages where the slug is /post-name/
function custom_parse_request_tricksy( $query ) {

    // Only noop the main query
    if ( ! $query->is_main_query() )

    // Only noop our very specific rewrite rule match
    if ( 2 != count( $query->query ) || ! isset( $query->query['page'] ) ) {

    // 'name' will be set if post permalinks are just post_name, otherwise the page rule will match
    if ( ! empty( $query->query['name'] ) ) {
        $query->set( 'post_type', array( 'post', 'photograph', 'page' ) );
add_action( 'pre_get_posts', 'custom_parse_request_tricksy' );

And that was our lesson in WordPress slug removing. Now you managed to have your own custom post type permalinks without the slug.

Share This

Subscribe to our blog

Register your e-mail address to receive regular news and updates from ColorLabs & Company

  • Sowmini

    Hi Natan,

    i am using a Classifier theme. i am unable to locate the pre-defined slug(add-new) for a custom post type (“Add New listing”) in theme-functions.php

    Could you please help here?


    • Natan

      “Add New Listing” is a page not custom post type. If you want to change pre-defined slug (add-new), you can change it from editing the “Add New Listing” page then change the slug (from edit page).

      FYI, all of the custom post type is defined inside theme-custom-type.php.

      You may contact our support if you have further question.

  • Gianmarco Zani

    You’re awesome Natan!
    I looked EVERYwhere for a solution to the problem but couldn’t find anything useful…. until I found your post!

    • ColorLabs & Company

      Hi Gianmarco,

      We’re glad that you find it useful. Thank you!

  • Sarah

    This appears to only work if your permalinks are set to post name. Trying to find something that will work for all.

    • Creative Slice

      Sarah, any luck finding a solution that will work if permalinks are NOT set to post name? We’re also looking for a more universal solution that allows us to keep nice urls for regular posts.

      • Sarah

        Yes, I keep trying to post my code but it must get filtered out. I will post to jsfiddle or the like and get you a link.

        • Oli.Hall

          Hi, I am also looking to be able to do this while post type is not set to %postname%. did you share your code anywhere? many thanks.

  • Jignesh Boricha

    It’s just the perfect solution what I am looking for. Thanks a lot for this post

    • ColorLabs & Company

      Hi Jignesh, we’re glad that you find it useful. Thank you for your feedback!

  • Guest

    How about server high-load after using this code, speed of page loading, garbage in mysql, problems with plugins?

  • kamah

    I’m looking for such a solution, but it seems that this one breaks slug edit button on the admin page…
    Any idea to fix it ?

  • Gizburdt

    Works! Awesome!

  • Gusswib

    Before i have the custom post ‘tour’ and i want to change the url with the new one ‘tours’ . How can i do it? thanks

  • Mark Kelly

    I’m working on a multisite that automatically adds ‘blog’ before all ‘post’ urls.

    I can specific to remove the ‘blog’ slug on the CPT by saying ‘With front = false’ on the cpt settings but after I do that the url returns a 404 error. I’m guessing this script will only work for one level of slug removal.. any thoughts?

Our Theme Collection

A collection of premium WordPress themes, designed for you by the experts