This is the code I am using:

<?php echo str_replace( home_url(), '', get_permalink($post->ID) ); ?>

What it does is output the permalink as a relative URL i.e. only the slug. For instance, if the permalink is http://example.com/2012/01/post-title/, the relative URL output by the code would look like /2012/01/post-title/.

Problem: All Posts and Pages show the right permalink, which is great. But all other pages (including Home, Search and Archives) show the relative URL of the first post and not that of the respective pages. Any idea why? What am I doing wrong here?

Reference: Get page permalink without wpurl

EDIT: Here's what else I've tried:

In functions.php

function get_relative_permalink( $url ) {
    $url = get_permalink();
    return str_replace( home_url(), "", $url );

In header.php

<link rel="alternate" hreflang="en-IN" href="http://in.example.com/<?php echo get_relative_permalink(); ?>" />

Same problem with this as well. But this one shows a not-so-informative error too.

  • Where exactly are you trying this code....?? Are you using global $post before your above code? Aug 28, 2012 at 13:31
  • @JoshuaAbenazer I am using the code as it is in my header.php file — looks like that's the wrong way of doing it. I will edit my question to reflect whatelse I've tried, so that you can help me better.
    – its_me
    Aug 28, 2012 at 13:35
  • 2
    Can I ask why you'd want this?
    – Tom J Nowell
    Aug 28, 2012 at 13:37
  • 1
    @TomJNowell Hey. I need to use a different domain for this markup: <link rel="alternate" hreflang="en-IN" href="http://in.example.com/2012/01/post-title/" /> — but the actual permalink is like this: http://example.com/2012/01/post-title/. (Reading this will give you a better idea of what I am doing.)
    – its_me
    Aug 28, 2012 at 13:41
  • If you want to go the WP way, you must realize get_permalink() is for getting instances of class WP_Post links (posts, pages, custom post types, ... )... for archives, tags, etc - just categories in general - instances of class WP_Term - it is get_term_link(), for home it is home_url()
    – jave.web
    Mar 18, 2018 at 19:49

3 Answers 3


Use $_SERVER['REQUEST_URI'] instead of get_permalink() to grab the current URL. get_permalink will give you the full address of the current post, not the address of the URL visited.

e.g. for example.com/test/page echo $_SERVER['REQUEST_URI']; prints /test/page

Note that this doesn't include the hashtag, as that part never gets sent to the server, and it also doesn't include ?foo=bar type parameters, those are in the $_GET array.

  • Works perfectly!!! Small correction — the second code is missing a quote. echo $_SERVER['REQUEST_URI']; — and thanks!
    – its_me
    Aug 28, 2012 at 13:51
  • @TomJNowell If I am not mistaken, $_SERVER['REQUEST_URI'] will give you the current URL, which may be a problem if it is a paginated post, meaning that /test/page/2 will be grabbed while using get_permalink() would be the solution for this issue. Am I making sense?
    – Christine Cooper
    Jun 10, 2014 at 18:36
  • Which is similar to what the original authors issue was, I would have to do some testing, but you can always add your own answer and if it works I'll upvote =]
    – Tom J Nowell
    Jun 10, 2014 at 20:34
  • Why was this answer accepted? It doesn't even remotely answer the OP's question! Jul 26, 2017 at 1:54
  • @JimMaguire it is defintely related to what OP asked, however answer author forgot to mention that it returns basically EVERYTHING after domain up to hash (which is not sent to server by design). So it is just a starting point, not the final solution.
    – jave.web
    Mar 18, 2018 at 19:59

I use

str_replace(home_url(), '', get_permalink()); 

If site root is not /

  • 1
    Nope, doesn't work when WP is in a subdirectory... Dec 27, 2014 at 8:17
  • What do you mean, when WP is in a subdirectory? Jul 26, 2017 at 1:53
  • 3
    @JimMaguire http://example.com/not-the-root-dir/
    – Walf
    Nov 8, 2017 at 6:17
  • 2
    No need to str_replace or preg_replace, just pass the permalink to [wp_make_link_relative][1](). [1]: developer.wordpress.org/reference/functions/… The built-in function is much simpler and also neatly handles trailing slashes, situations where home_url and site_url are different and various other edge cases.
    – senectus
    Nov 19, 2021 at 12:05

This works for me:

function force_relative_url ($url)
    return preg_replace ('/^(http)?s?:?\/\/[^\/]*(\/?.*)$/i', '$2', '' . $url);

To use it on a permalink:

$relative_permalink = force_relative_url (get_permalink ($post->ID));

Not the answer you're looking for? Browse other questions tagged or ask your own question.