422

I have URL like: http://example.com#something, how do I remove #something, without causing the page to refresh?

I attempted the following solution:

window.location.hash = '';

However, this doesn't remove the hash symbol # from the URL.

Rahul Gupta
  • 9,775
  • 7
  • 56
  • 69
Tom Lehman
  • 85,973
  • 71
  • 200
  • 272
  • 4
    Do you really want to do this? It'll cause a page refresh. – seth Sep 09 '09 at 03:08
  • 13
    Is it possible to do without a page refresh? – Tom Lehman Sep 09 '09 at 03:11
  • 1
    It *is* possible. AJAX history libraries deal with it. But it's not easy, and it has to be done differently for almost every browser. Not something you wanna get into. – Gabriel Hurley Sep 09 '09 at 03:14
  • Is there any conciderations with leaving a "#" behind other than a visual one? – user29660 Aug 16 '16 at 10:55
  • Possible duplicate of [Modify the URL without reloading the page](https://stackoverflow.com/questions/824349/modify-the-url-without-reloading-the-page) – PayteR Sep 10 '17 at 12:53
  • and [Remove fragment in URL with JavaScript w/out causing page reload](https://stackoverflow.com/q/269044) – djvg Mar 30 '23 at 09:22

18 Answers18

682

Solving this problem is much more within reach nowadays. The HTML5 History API allows us to manipulate the location bar to display any URL within the current domain.

function removeHash () { 
    history.pushState("", document.title, window.location.pathname
                                                       + window.location.search);
}

Working demo: http://jsfiddle.net/AndyE/ycmPt/show/

This works in Chrome 9, Firefox 4, Safari 5, Opera 11.50 and in IE 10. For unsupported browsers, you could always write a gracefully degrading script that makes use of it where available:

function removeHash () { 
    var scrollV, scrollH, loc = window.location;
    if ("pushState" in history)
        history.pushState("", document.title, loc.pathname + loc.search);
    else {
        // Prevent scrolling by storing the page's current scroll offset
        scrollV = document.body.scrollTop;
        scrollH = document.body.scrollLeft;

        loc.hash = "";

        // Restore the scroll offset, should be flicker free
        document.body.scrollTop = scrollV;
        document.body.scrollLeft = scrollH;
    }
}

So you can get rid of the hash symbol, just not in all browsers — yet.

Note: if you want to replace the current page in the browser history, use replaceState() instead of pushState().

Andy E
  • 338,112
  • 86
  • 474
  • 445
  • 9
    Use this line to make sure you don't lose the query string: history.pushState("", document.title, window.location.pathname + window.location.search); – Phil Kulak Mar 13 '12 at 15:56
  • 6
    @Phil: thanks for pointing that out, I've updated the answer accordingly. I'm too used to using pretty URLs. – Andy E Mar 13 '12 at 17:32
  • 1
    For older versions of IE, it seems you need to use document.documentElement instead of document.body. See this answer http://stackoverflow.com/a/2717272/359048 – jasonmcclurg Aug 14 '13 at 23:09
  • 50
    I suggest using replaceState instead of pushState, to not create an extra entry in the browser history. – Nico Oct 06 '13 at 13:12
  • Is there any difference between [location.hash=" ";] and calling the suggested function [removeHash();]. becoz for me, both are giving the same error at console as : [Error: 10 $digest() iterations reached. Aborting!] Any suggestion ? – NawazSE Sep 18 '14 at 05:38
  • I think history.pushState will not trigger **hashshange** whereas window.location.hash will. To me this event is very important, so just be careful – santiago arizti Oct 22 '18 at 23:16
  • @santiagoarizti: `history.pushState()` **will** trigger a *hashchange* event. The fiddle in my answer demonstrates this by toggling the disabled state of a button in the *hashchange* event. – Andy E Oct 23 '18 at 14:49
  • interesting, I made my own fiddle to demonstrate that it didn't work before I wrote a comment here... look: https://jsfiddle.net/k76qefn1/ – santiago arizti Oct 23 '18 at 15:20
  • ok, I inspected your fiddle and the "hashchange" event only triggers on the `href="#hash"` click, which is to be expected, but it doesn't trigger after `history.pushState` which is what I am warning people about – santiago arizti Oct 23 '18 at 15:26
  • 1
    @santiagoarizti: you're right, I just came to the same conclusion. I didn't inspect the code I wrote (7 years ago!) properly and missed that I was also toggling the state of the button when removing the hash. Since you are changing the hash manually, you could always trigger the event yourself, I suppose. – Andy E Oct 23 '18 at 15:30
  • In (at least) Firefox 63, you will need a full URL (including domain name) to satisfy security checks. `history.replaceState('', document.title, window.location.origin + window.location.pathname + window.location.search);` Note addition of "window.location.origin". The answer, as given above, does not work in Chrome 70, but this modification does. Tested in Firefox 63, Chrome 70, IE 11, Edge. – Neil Monroe Nov 02 '18 at 23:43
  • OK, it seems that the problem was underspecified by the original poster, so I need to specify: I need to have ABSOLUTE, AUTOCRATIC AND TYRANNICAL CONTROL over the following aspects of behavior INDEPENDENTLY: 1) the hash part of the URL in the location changing 2) the trailing # in the URL staying or being gone after `location.hash=""` 3) scrolling to the anchor 4) triggering of the hashchange event No one who cannot offer a reliable implementation of `setHash(hash, shouldChangeLocationBar, shouldHashRemain, shouldScroll, shouldTriggerEvent)` can claim to have solved The Problem. – Szczepan Hołyszewski Feb 27 '19 at 18:55
  • @Nico Your comment is very helpful for at time of back button because I don't want to back path with #string. Thank for my time-saving. – Bhavin Thummar May 29 '19 at 11:11
243

Initial question:

window.location.href.substr(0, window.location.href.indexOf('#'))

or

window.location.href.split('#')[0]

both will return the URL without the hash or anything after it.

With regards to your edit:

Any change to window.location will trigger a page refresh. You can change window.location.hash without triggering the refresh (though the window will jump if your hash matches an id on the page), but you can't get rid of the hash sign. Take your pick for which is worse...

MOST UP-TO-DATE ANSWER

The right answer on how to do it without sacrificing (either full reload or leaving the hash sign there) is up here. Leaving this answer here though with respect to being the original one in 2009 whereas the correct one which leverages new browser APIs was given 1.5 years later.

Derek Adair
  • 21,846
  • 31
  • 97
  • 134
Gabriel Hurley
  • 39,690
  • 13
  • 62
  • 88
  • 27
    This is just plain wrong, you can change window.location.hash and it will not trigger a refresh. – Evgeny Oct 31 '10 at 20:21
  • 64
    @Evgeny -- That's what my answer says. I explicitly say that changing window.location.hash won't trigger a refresh. "You can change window.location.hash without triggering the refresh (though the window will jump if your hash matches an id on the page)". – Gabriel Hurley Oct 31 '10 at 22:29
  • 3
    No page reload - that is in the question. This is not the answer as it requires/forces a page reload! – Ed_ May 28 '12 at 16:56
  • 14
    also think it should not be the ✓answer – abernier Jun 19 '12 at 13:38
  • 1
    @abernier Agreed, doesn't say how do to remove the hash from the URL, just the URL string. – Belladonna Apr 02 '13 at 17:01
  • 2
    If the href has a #, both the substr and split methods will work. But if the href has no #, the substr method returns empty string, while the split returns the href. – dlaliberte May 22 '13 at 20:49
  • 1
    @LittleBigBot obviously just: window.location = window.location.href.split('#')[0]; ... – AO_ Aug 09 '13 at 14:08
  • @smftre I think I meant that it doesn't specify how to remove the hash from `window.location`, but it just removes it from the string it returns. – Belladonna Aug 12 '13 at 19:18
  • 4
    This is not an answer to the OP question. – Bryce Nov 14 '13 at 23:42
  • "Leaving this answer here though with respect to being the original one in 2009 whereas the correct one which leverages new browser APIs was given 1.5 years later." The best answer should be at the top, not the first or whatever. This isn't about status. It's about getting the best information to people. Either edit this answer to include the better information or make the better information the accepted answer. – Trott Apr 21 '17 at 18:42
  • this is the correct answer and perfectly explained. – tfont Sep 06 '17 at 15:28
  • thanks for updating with the current answer later in the thread OP <3 – Thomas Oct 09 '17 at 15:16
  • @Evgeny `window.location.hash=""` will remove the hash id , but the hash at the end of the url will remain eg: `/index.html#id` becomes `/index.html#` – 27px Dec 05 '20 at 14:34
  • @dlaliberte if there is no delimeter in s string to split split() function will return the original string in an array not empty string eg: `"/index.html#id".split("#") // ["/index.html","id"]` and `"/index.html".split("#") // ["/index.html"]` – 27px Dec 05 '20 at 14:38
160

(Too many answers are redundant and outdated.) The best solution now is this:

history.replaceState(null, null, ' ');
Pacerier
  • 86,231
  • 106
  • 366
  • 634
50

Simple and elegant:

history.replaceState({}, document.title, ".");  // replace / with . to keep url
Community
  • 1
  • 1
cprcrack
  • 17,118
  • 7
  • 88
  • 91
30

You can do it as below:

history.replaceState({}, document.title, window.location.href.split('#')[0]);
Kerem
  • 11,377
  • 5
  • 59
  • 58
METALHEAD
  • 2,734
  • 3
  • 22
  • 37
15

This will remove the trailing hash as well. eg: http://test.com/123#abc -> http://test.com/123

if(window.history.pushState) {
    window.history.pushState('', '/', window.location.pathname)
} else {
    window.location.hash = '';
}
Chris Gunawardena
  • 6,246
  • 1
  • 29
  • 45
15

To remove the hash, you may try using this function

function remove_hash_from_url()
{
    var uri = window.location.toString();
    if (uri.indexOf("#") > 0) {
        var clean_uri = uri.substring(0, uri.indexOf("#"));
        window.history.replaceState({}, document.title, clean_uri);
    }
}
Rahul Gupta
  • 9,775
  • 7
  • 56
  • 69
6

How about the following?

window.location.hash=' '

Please note that am setting the hash to a single space and not an empty string.


Setting the hash to an invalid anchor does not cause a refresh either. Such as,

window.location.hash='invalidtag'

But, I find above solution to be misleading. This seems to indicate that there is an anchor on the given position with the given name although there isn't one. At the same time, using an empty string causes page to move to the top which can be unacceptable at times. Using a space also ensures that whenever the URL is copied and bookmarked and visited again, the page will usually be at the top and the space will be ignored.

And, hey, this is my first answer on StackOverflow. Hope someone finds it useful and it matches the community standards.

Nibras Reeza
  • 127
  • 1
  • 6
6
const url = new URL(window.location);
url.hash = '';
history.replaceState(null, document.title, url);
Casey
  • 1,802
  • 3
  • 22
  • 35
  • 2
    While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value. – rollstuhlfahrer Apr 02 '18 at 07:07
5
function removeLocationHash(){
    var noHashURL = window.location.href.replace(/#.*$/, '');
    window.history.replaceState('', document.title, noHashURL) 
}

window.addEventListener("load", function(){
    removeLocationHash();
});
Vimal Kumar
  • 61
  • 1
  • 3
3
<script type="text/javascript">
var uri = window.location.toString();
if (uri.indexOf("?") > 0) {
    var clean_uri = uri.substring(0, uri.indexOf("?"));
    window.history.replaceState({}, document.title, clean_uri);
}
</script>

put this code on head section

2

I think, it would be more safe

if (window.history) {
    window.history.pushState('', document.title, window.location.href.replace(window.location.hash, ''));
} else {
    window.location.hash = '';
}
1
if (window.location.href.includes('#')) {
    const cleanedUrl = window.location.href.split('#')[0];
    window.history.replaceState(null, null, cleanedUrl);
}
paulalexandru
  • 9,218
  • 7
  • 66
  • 94
0

Try the following:

window.history.back(1);
josliber
  • 43,891
  • 12
  • 98
  • 133
0

Here is another solution to change the location using href and clear the hash without scrolling.

The magic solution is explained here. Specs here.

const hash = window.location.hash;
history.scrollRestoration = 'manual';
window.location.href = hash;    
history.pushState('', document.title, window.location.pathname);

NOTE: The proposed API is now part of WhatWG HTML Living Standard

voscausa
  • 11,253
  • 2
  • 39
  • 67
0
$(window).on('hashchange', function (e) {
    history.replaceState('', document.title, e.oldURL);
});
Kerem
  • 11,377
  • 5
  • 59
  • 58
JohnMathew
  • 508
  • 1
  • 5
  • 21
0

Building off one of the answers given above, use this:

var scrollV, scrollH
var loc = window.location;
scrollV = document.body.scrollTop;
scrollH = document.body.scrollLeft;
if ("pushState" in history) {
    history.pushState("", document.title, loc.pathname + loc.search);

    // Restore the scroll offset
    document.body.scrollTop = scrollV;
    document.body.scrollLeft = scrollH;

} else {
    loc.hash = "";

    // Restore the scroll offset
    document.body.scrollTop = scrollV;
    document.body.scrollLeft = scrollH;
}
Engineersticity
  • 351
  • 2
  • 5
-5

You can replace hash with null

var urlWithoutHash = document.location.href.replace(location.hash , "" );
Devang Bhagdev
  • 633
  • 2
  • 8
  • 14
  • 1
    The question asks "without causing the page to refresh", but this method does refresh the page. You should note this fact in your answer, so we don't all have to waste our time finding out firsthand that you're answering a different question than the one we're actually trying to get answered here. – Val Kornea Jan 09 '15 at 00:41
  • It does not refresh the page. – Ciprian Jul 01 '16 at 10:08
  • It does not refresh the page because it isn't updating the URL. `replace` returns a fresh new string and `location.href` remains the same. As soon as you do `location.href = urlWithouthHash` you will get the refresh. – adripanico Feb 04 '21 at 15:56