2978

Is there a way I can modify the URL of the current page without reloading the page?

I would like to access the portion before the # hash if possible.

I only need to change the portion after the domain, so it's not like I'm violating cross-domain policies.

 window.location.href = "www.mysite.com/page2.php";  // this reloads
Web Developer
  • 333
  • 4
  • 17
Robin Rodricks
  • 110,798
  • 141
  • 398
  • 607
  • 185
    Just to make it easier to understand the question, this is what Facebook does when you open a photo, for example. The url bar changes to point DIRECTLY to that photo, so you can share the URL without losing where you are in the site. Remember sites based on framing last decade? You could only get the homepage url, because only internal frames were changing. And that was terrible. – Spidey Apr 19 '12 at 17:59
  • 7
    While `history.pushState()` is probably the right answer here, in this situation (depending on the exact circumstances...) the possibility of using a server-side redirect (such as via using Apache's RewriteRule directive) is something you might want to consider, or at least be aware of. Just thought it should be mentioned! – Doin Mar 14 '20 at 06:37
  • 12
    `window.history.replaceState(null, document.title, "/page2.php")` is probably what most people are looking for. – Ninjakannon Dec 09 '21 at 15:50

21 Answers21

2404

This can now be done in Chrome, Safari, Firefox 4+, and Internet Explorer 10pp4+!

See this question's answer for more information: Updating address bar with new URL without hash or reloading the page

Example:

 function processAjaxData(response, urlPath){
     document.getElementById("content").innerHTML = response.html;
     document.title = response.pageTitle;
     window.history.pushState({"html":response.html,"pageTitle":response.pageTitle},"", urlPath);
 }

You can then use window.onpopstate to detect the back/forward button navigation:

window.onpopstate = function(e){
    if(e.state){
        document.getElementById("content").innerHTML = e.state.html;
        document.title = e.state.pageTitle;
    }
};

For a more in-depth look at manipulating browser history, see this MDN article.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
David Murdoch
  • 87,823
  • 39
  • 148
  • 191
  • 12
    Please note the OP makes it clear they are **not trying to navigate to a different origin**; "not like I'm violating cross-domain policies." -- however, I **am** trying to do that, and the [`window.history` API](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState) does not allow cross-origin navigation via `pushState`, (which is reasonable... as the Mozilla site says, " The new URL must be of the same origin as the current URL; otherwise, pushState() will throw an exception.") – Nate Anderson Mar 17 '21 at 19:29
  • 1
    Can I asks what is the value of response.html? Is that a string of HTML? – Edison Pebojot May 19 '21 at 05:42
  • 3
    What data should be passed to "response"? – DeeStarks Jun 04 '21 at 21:32
  • @EdisonPebojot when you change the URL, you're expected to also change the html content of he page. Where you get that HTML is totally up to the developer and you don't have to do it like in this example. You also need to support back/forward buttons and re-create the page content. – Abhi Beckert Feb 07 '22 at 03:53
  • Is there any workaround for changing it with a different domain? This works only when the target URL is under the same domain. – sshanzel Jun 21 '22 at 09:30
  • @sshanzel there's no reason to do that - are you trying to do some phishing site? - btw, I think it's possible to set the URL to about:blank - but I'm not sure. I saw that - some steam scam. – france1 Oct 02 '22 at 07:03
  • @france1 thank you for replying, after some reading, I fully understood the reason behind being unable to make it work. With that, the reason behind was, I was working on a chrome extension with a mirror equivalent hosted in a domain. So when I opened a modal, I wanted to change the URL to have the parameters to point to that specific hosted page. So when the user refreshes, the opened modal with specific parameters will be retained. – sshanzel Oct 03 '22 at 05:58
  • Dang. My app's url has changed due to dynamic hosting that timed out. Now I want to basically transfer the app (that is running in my browser) to the new url without losing any state. Is that not possible? – Qwerty Apr 24 '23 at 11:17
827

HTML5 introduced the history.pushState() and history.replaceState() methods, which allow you to add and modify history entries, respectively.

window.history.pushState('page2', 'Title', '/page2.php');

Read more about this from here

squarecandy
  • 4,894
  • 3
  • 34
  • 45
Vivart
  • 14,900
  • 6
  • 36
  • 74
  • 3
    Great answer, also can change the current history rather than adding another one, using replaceState(); https://developer.mozilla.org/en-US/docs/Web/API/History_API/Working_with_the_History_API#the_replacestate_method – iYazee6 Jul 12 '21 at 13:23
  • 1
    I get `A history state object with URL 'file:///C:/Users/.../newUrl' cannot be created in a document with origin 'null' and URL 'file:///C:/Users/.../oldUrl.pdf' `. Is it because it's a local disk URL? – golimar Feb 01 '22 at 09:58
  • What happens if I use `null` as the first parameter of `pushState()`? – Rodrigo May 09 '22 at 15:44
217

You can also use HTML5 replaceState if you want to change the url but don't want to add the entry to the browser history:

if (window.history.replaceState) {
   //prevents browser from storing history with each change:
   window.history.replaceState(statedata, title, url);
}

This would 'break' the back button functionality. This may be required in some instances such as an image gallery (where you want the back button to return back to the gallery index page instead of moving back through each and every image you viewed) whilst giving each image its own unique url.

George Filippakos
  • 16,359
  • 15
  • 81
  • 92
187

Here is my solution (newUrl is your new URL which you want to replace with the current one):

history.pushState({}, null, newUrl);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Haimei
  • 12,577
  • 3
  • 50
  • 36
  • 9
    Best to test first with if (history.pushState) {} Just in case old browser. – Craig Jacobs Aug 29 '16 at 00:14
  • 1
    This doesn't work any more you will get in Firefox: The operation is insecure. – kkatusic Nov 09 '17 at 10:19
  • And the user can even set a bookmark with that approach, beautiful! I can now update the url on user input and he can directly bookmark whatever his settings are. – codepleb Jun 03 '20 at 07:26
  • 1
    hey kkatusic, thats why Craig Jacobs said TEST. You Test it by trying to execute the new html5 version (test 1) and if that fails you test the older version and if that fails you have problems, if the test succeeds for either object then you know if the brower is new or old. pretty simple logic buddy! Upvote for Craig! :) – Gregory Bowers Oct 06 '20 at 08:44
  • @GregoryBowers I don't think kkatusic is saying the method doesn't exist, he said it shows a security error/warning when run. So that test would not fail and would still run the function. The test suggested by Craig does not "try to execute the new html5" function, it just checks it exists in the history object. – scipilot May 28 '21 at 04:39
  • This works only if newUrl is RELATIVE or is the same as the current url, and respecting the current protocole, for example if it's https the newUrl should be the same, won't work with http even they have the same base url. Tested in Firefox (93), Edge (94), Chrome (94). – moghwan Oct 12 '21 at 09:03
119

NOTE: If you are working with an HTML5 browser then you should ignore this answer. This is now possible as can be seen in the other answers.

There is no way to modify the URL in the browser without reloading the page. The URL represents what the last loaded page was. If you change it (document.location) then it will reload the page.

One obvious reason being, you write a site on www.mysite.com that looks like a bank login page. Then you change the browser URL bar to say www.mybank.com. The user will be totally unaware that they are really looking at www.mysite.com.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Robin Day
  • 100,552
  • 23
  • 116
  • 167
94
parent.location.hash = "hello";
Martin.
  • 10,494
  • 3
  • 42
  • 68
  • 21
    I want to change the URL, not just the hash -- #mydata – Robin Rodricks May 14 '09 at 18:26
  • 43
    Changing the hash can be useful in ajax as it's a kind of state without using cookies, is bookmarkable, and compatible with browser back buttons. Gmail uses this nowadays to make it more browser friendly. – Matthew Lock Nov 24 '09 at 08:32
  • @Jarvis: what is the difference? – noisy Jul 17 '13 at 07:07
  • @noisy Server side tracking cannot see hashes unless sent to the tracking service explicitly. – MLK.DEV Nov 06 '14 at 22:07
  • this is not useful if you're using an mvc framework that routes on hash, for example backbone. – catbadger Feb 01 '17 at 13:57
  • @catbadger I beg to differ. It's _particularly_ useful if you're using an MVC framework that routes on hash. My use case is that my page gets updated via AJAX, but I want the URL to always reflect those updates. If my routing does not use the hash, I _must_ use the HTML5 `pushState()` method, but if it uses hash I can use this. – Auspex Jun 04 '21 at 10:35
  • 2
    This only partially answers the question. We want the url to change, not the hash. – AksLolCoding Jul 23 '21 at 16:57
  • OP specified in the post that they wanted to do it before the hash. This answer isn't helpful (especially because people who want to and don't know how to update the hash probably wouldn't be browsing answers on a question that says no hash). – Raphael Morgan Dec 03 '21 at 12:44
81

In modern browsers and HTML5, there is a method called pushState on window history. That will change the URL and push it to the history without loading the page.

You can use it like this, it will take 3 parameters, 1) state object 2) title and a URL):

window.history.pushState({page: "another"}, "another page", "example.html");

This will change the URL, but not reload the page. Also, it doesn't check if the page exists, so if you do some JavaScript code that is reacting to the URL, you can work with them like this.

Also, there is history.replaceState() which does exactly the same thing, except it will modify the current history instead of creating a new one!

Also you can create a function to check if history.pushState exist, then carry on with the rest like this:

function goTo(page, title, url) {
  if ("undefined" !== typeof history.pushState) {
    history.pushState({page: page}, title, url);
  } else {
    window.location.assign(url);
  }
}

goTo("another page", "example", 'example.html');

Also, you can change the # for <HTML5 browsers, which won't reload the page. That's the way Angular uses to do SPA according to hashtag...

Changing # is quite easy, doing like:

window.location.hash = "example";

And you can detect it like this:

window.onhashchange = function () {
  console.log("#changed", window.location.hash);
}
turivishal
  • 34,368
  • 7
  • 36
  • 59
Alireza
  • 100,211
  • 27
  • 269
  • 172
28

The HTML5 replaceState is the answer, as already mentioned by Vivart and geo1701. However it is not supported in all browsers/versions. History.js wraps HTML5 state features and provides additional support for HTML4 browsers.

27

Before HTML5 we can use:

parent.location.hash = "hello";

and:

window.location.replace("http:www.example.com");

This method will reload your page, but HTML5 introduced the history.pushState(page, caption, replace_url) that should not reload your page.

Patrioticcow
  • 26,422
  • 75
  • 217
  • 337
Shine
  • 882
  • 8
  • 15
  • 2
    The problem with `history.pushState(..)` is, that if you want to redirect to another domain, the cross domain policy come in effect. While with `window.location.replace(..)`redirecting to another domain is possible. – OSWorX May 12 '18 at 09:00
26

If what you're trying to do is allow users to bookmark/share pages, and you don't need it to be exactly the right URL, and you're not using hash anchors for anything else, then you can do this in two parts; you use the location. hash discussed above, and then implement a check on the home page, to look for a URL with a hash anchor in it, and redirect you to the subsequent result.

For instance:

  1. User is on www.site.com/section/page/4

  2. User does some action which changes the URL to www.site.com/#/section/page/6 (with the hash). Say you've loaded the correct content for page 6 into the page, so apart from the hash the user is not too disturbed.

  3. User passes this URL on to someone else, or bookmarks it

  4. Someone else, or the same user at a later date, goes to www.site.com/#/section/page/6

  5. Code on www.site.com/ redirects the user to www.site.com/section/page/6, using something like this:

if (window.location.hash.length > 0){ 
   window.location = window.location.hash.substring(1);
}

Hope that makes sense! It's a useful approach for some situations.

JoSSte
  • 2,953
  • 6
  • 34
  • 54
Jeremy Warne
  • 3,437
  • 2
  • 30
  • 28
22

You can use this beautiful and simple function to do so anywhere on your application.

function changeurl(url, title) {
    var new_url = '/' + url;
    window.history.pushState('data', title, new_url);
    
}

You can not only edit the URL but you can update the title along with it.

turivishal
  • 34,368
  • 7
  • 36
  • 59
Dheeraj Thedijje
  • 1,053
  • 12
  • 19
19

Below is the function to change the URL without reloading the page. It is only supported for HTML5.

  function ChangeUrl(page, url) {
        if (typeof (history.pushState) != "undefined") {
            var obj = {Page: page, Url: url};
            history.pushState(obj, obj.Page, obj.Url);
        } else {
            window.location.href = "homePage";
            // alert("Browser does not support HTML5.");
        }
    }

  ChangeUrl('Page1', 'homePage');
Onur A.
  • 3,007
  • 3
  • 22
  • 37
Suraj
  • 2,181
  • 2
  • 17
  • 25
  • 2
    @Green, page is a short title for the state to which you're moving. Firefox currently ignores this parameter, although it may use it in the future. Passing the empty string here should be safe against future changes to the method. From: https://developer.mozilla.org/en-US/docs/Web/API/History_API#The_pushState()_method – Snook May 27 '16 at 07:41
13

Any changes of the loction (either window.location or document.location) will cause a request on that new URL, if you’re not just changing the URL fragment. If you change the URL, you change the URL.

Use server-side URL rewrite techniques like Apache’s mod_rewrite if you don’t like the URLs you are currently using.

Gumbo
  • 643,351
  • 109
  • 780
  • 844
11

You can add anchor tags. I use this on my site so that I can track with Google Analytics what people are visiting on the page.

I just add an anchor tag and then the part of the page I want to track:

var trackCode = "/#" + urlencode($("myDiv").text());
window.location.href = "http://www.piano-chords.net" + trackCode;
pageTracker._trackPageview(trackCode);
Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
Nate
  • 127
  • 1
  • 2
9

As pointed out by Thomas Stjernegaard Jeppesen, you could use History.js to modify URL parameters whilst the user navigates through your Ajax links and apps.

Almost an year has passed since that answer, and History.js grew and became more stable and cross-browser. Now it can be used to manage history states in HTML5-compliant as well as in many HTML4-only browsers. In this demo You can see an example of how it works (as well as being able to try its functionalities and limits.

Should you need any help in how to use and implement this library, i suggest you to take a look at the source code of the demo page: you will see it's very easy to do.

Finally, for a comprehensive explanation of what can be the issues about using hashes (and hashbangs), check out this link by Benjamin Lupton.

Erenor Paz
  • 3,061
  • 4
  • 37
  • 44
8

Use history.pushState() from the HTML 5 History API.

Refer to the HTML5 History API for more details.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Prathamesh Rasam
  • 416
  • 4
  • 11
8

Your new url.

let newUrlIS =  window.location.origin + '/user/profile/management';

In a sense, calling pushState() is similar to setting window.location = "#foo", in that both will also create and activate another history entry associated with the current document. But pushState() has a few advantages:

history.pushState({}, null, newUrlIS);

You can check out the root: https://developer.mozilla.org/en-US/docs/Web/API/History_API

Vinay Kaithwas
  • 1,415
  • 10
  • 17
1

This code works for me. I used it into my application in ajax.

history.pushState({ foo: 'bar' }, '', '/bank');

Once a page load into an ID using ajax, It does change the browser url automatically without reloading the page.

This is ajax function bellow.

function showData(){
    $.ajax({
      type: "POST",
      url: "Bank.php", 
      data: {}, 
      success: function(html){          
        $("#viewpage").html(html).show();
        $("#viewpage").css("margin-left","0px");
      }
    });
  }

Example: From any page or controller like "Dashboard", When I click on the bank, it loads bank list using the ajax code without reloading the page. At this time, browser URL will not be changed.

history.pushState({ foo: 'bar' }, '', '/bank');

But when I use this code into the ajax, it change the browser url without reloading the page. This is the full ajax code here in the bellow.

function showData(){
        $.ajax({
          type: "POST",
          url: "Bank.php", 
          data: {}, 
          success: function(html){          
            $("#viewpage").html(html).show();
            $("#viewpage").css("margin-left","0px");
            history.pushState({ foo: 'bar' }, '', '/bank');
          }
        });
      }
1

These two lines are all you need.

    var new_url="Your modified URL";
    window.history.pushState(null,"",new_url);
  • How is this answer different from Alireza's answer in 2017? All you did was create a variable for the `new_url` - otherwise, it is the exact same answer without the additional explanation. Also, you did not explain the purpose of the "data" or "Title" parameters, or how they can be used. Please delete this unnecessary answer. -1 – cssyphus Apr 22 '23 at 14:32
  • Sorry for that. I edited my answer because I copy and pasted from my old project. I didn't explain it correctly and I forgot to change the details. Maybe this answer is not different. But, It worked for me. Thank anyway. :) – Shehan Sachintha Apr 23 '23 at 19:30
-1

This is all you will need to navigate without reload

// add setting without reload 
location.hash = "setting";

// if url change with hash do somthing
window.addEventListener('hashchange', () => {
    console.log('url hash changed!');
});

// if url change do somthing (dont detect changes with hash)
//window.addEventListener('locationchange', function(){
//    console.log('url changed!');
//})


// remove #setting without reload 

history.back();
Community
  • 1
  • 1
Omar bakhsh
  • 896
  • 11
  • 18
-16

Simply use, it will not reload the page, but just the URL :

$('#form_name').attr('action', '/shop/index.htm').submit();
James Bond
  • 2,825
  • 2
  • 15
  • 11
  • 13
    This makes no sense – Stefan Reich Aug 27 '21 at 07:08
  • 3
    This requires jQuery even if jQuery has never been mentioned in the question. This calls `submit` on a `
    ` which, by default, reloads the page, which was specifically requested to be avoided. _“it will not reload the page, but just the URL”_ is guaranteed to be false. Why was this posted as an answer to this question?
    – Sebastian Simon Mar 26 '22 at 23:54