40

How do you get and set URL hash parameters in pure JavaScript?

For example, I'd like to use parameters like this: myurl.com/#from=2012-01-05&to=2013-01-01

And I'd like to be able to get and set the from and to parameters in the above.

I'm happy to use the HTML5 history API if that's the best way of doing things.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
Richard
  • 62,943
  • 126
  • 334
  • 542

8 Answers8

73

If you want to parse a hash URL:

var hash = window.location.hash.substr(1);

var result = hash.split('&').reduce(function (res, item) {
    var parts = item.split('=');
    res[parts[0]] = parts[1];
    return res;
}, {});

That way, if you have this: http://example.com/#from=2012-01-05&to=2013-01-01

It becomes: {'from': '2012-01-05', 'to':'2013-01-01'}

As @Dean Stamler notes in the comments, dont forget the empty starting object. }, {});

Now to set a hash URL:

window.location.hash = "from=2012-01-05&to=2013-01-01";

crthompson
  • 15,653
  • 6
  • 58
  • 80
  • @RickS, result is an array of all the params. Note that "from" and "to" are multiple params. Please test it out, it works just fine with multiple params. – crthompson Sep 06 '18 at 16:13
  • 1
    @RickS if it's not working for multiple params it's very likely that you haven't included the empty object `{}` as a second argument to the `reduce()` call. This is the initial value of the accumulator. – Dean Stamler Mar 18 '19 at 15:46
  • A bit confusing to have the intermediate result and the final result share the same variable name IMO – Charlton Provatas Nov 07 '20 at 00:55
13

You can set the hash with:

window.location.hash = "new value";

and (in newer browsers) listen to changes with:

window.addEventListener("hashchange", function () {
});

If you need to support browsers that don't support "hashchange" you'll want to use code that other people have written, such as jquery's history plugin.

Halcyon
  • 57,230
  • 10
  • 89
  • 128
  • Which older browsers do not support `location.hash`? (Btw, it's `window.` usually not `document.`) – Bergi May 16 '14 at 16:00
  • `location.hash` is well supported, but not `"hashchange"`. For older versions of IE you need a hack that involves an iframe. See: http://caniuse.com/#search=hashchange – Halcyon May 16 '14 at 16:00
  • Yeah, that's what I expected, but your phrasing "*Newer versions of browsers support setting*" is confusing. – Bergi May 16 '14 at 16:05
  • I just want to make it abundantly clear that there compatibility issues. – Halcyon May 16 '14 at 16:06
11

As for getting parameters... how about this solution:

var myUrl = new URL(window.location.href.replace(/#/g,"?"));
var param_value = myUrl.searchParams.get("param_name");

Wish u luck!

Toma
  • 519
  • 7
  • 8
  • 2
    It will work properly only if the url doesn't have any query parameters yet (and doesn't contain `?` yet). So for example for this url it will not work: https://stackoverflow.com/?lala=kuku#bebe=nene – Alexander Jan 03 '22 at 20:03
  • @Alexander You can solve that issue like this `var myUrl = new URL('a://' + window.location.hash.replace(/^#/g,"?"))` (`a://` is just the shortest possible "valid" url) – Lindsay-Needs-Sleep May 05 '23 at 06:29
6

The other answers don't address the problem

I got a way easier approach:

Copy over current hashparameters to a dummy URL as searchParameters. Now you can treat the hash parameters like search-parameters and copy them back afterwards:

Simple function

function setOrUpdateHashParameter( hashParameterName, hashParameterValue ) {
    let theURL              = new URL('https://dummy.com');             // create dummy url
    theURL.search           = window.location.hash.substring(1);        // copy current hash-parameters without the '#' AS search-parameters
    theURL.searchParams.set( hashParameterName, hashParameterValue );   // set or update value with the searchParams-API
    window.location.hash    = theURL.searchParams;                      // Write back as hashparameters
}
crthompson
  • 15,653
  • 6
  • 58
  • 80
Marrt
  • 135
  • 2
  • 6
  • 1
    Be aware, that it is not working in Internet Explorer 11. https://developer.mozilla.org/en-US/docs/Web/API/URL/URL#Browser_compatibility – Markus Oct 22 '19 at 09:17
3

For Multiple Params:

const href = window.location.href;
const params = href.split('?')[1];

// Be sure url params exist
if (params && params !== '') {
    const result = params.split('&').reduce(function (res, item) {
        const parts = item.split('=');
        res[parts[0]] = parts[1];
        return res;
    }, {});
}

Therefore, when href=https://www.example.net/page.html#/page1?foo=bar&token=123abc the result will evaluate to {foo: "bar", token: "123abc"}.

This structure requires that the URL has the question mark ? before the params, an equal sign = between the variable key and value, and a & between each key/value pair.

  • Hey! I am trying to use your code snippet and it returns only the last hash value in object. Do you know why it can happen? I am using `window.location.hash` and before applying `reduce`, I do this: `decodeURI(window.location.hash).substr(1).split('&')`. – Olga B May 20 '20 at 11:29
  • The example of url I have: `www.example.com#word=foo&word=bar`. Can it be because I have same key (`word`) for parameters? – Olga B May 20 '20 at 11:36
  • 1
    @OlgaB using this snippet, you need to use a `?` to split the params from the rest. You can also replace the `?` in `const params` with `#`. – Christopher Chalfant May 21 '20 at 12:38
2

For get only:

const startingUrl = 'https://stackoverflow.com/questions/23699666/javascript-get-and-set-url-hash-parameters#state=XXX&b=YYY'
const myUrl = new URL(startingUrl);
const hash = new URLSearchParams(myUrl.hash.substring(1))
hash.get('state'); // XXX
hash.get('b'); // YYY

enter image description here

Felix
  • 3,999
  • 3
  • 42
  • 66
1

Based upon Maart's answer here is a version which returns the edited URL rather than applying the change to the current window.

function setHashParam(url, name, value) {

    // Create URL objects for the url we want to change and a dummy url (requires a polyfill for IE)
    var urlObj = new URL(url);
    var dummyObj = new URL('https://dummy.com');

    // Copy current hash-parameters without the '#' as search-parameters
    dummyObj.search = urlObj.hash.substring(1);

    // Set or update value with the searchParams-API (requires a polyfill for IE)
    dummyObj.searchParams.set(name, value);

    // Write back as hashparameters
    urlObj.hash = dummyObj.searchParams;

    return urlObj.href;
}

Note that for this answer (and Maart's) to work in IE they require polyfills for the URL constructor and the search params API.

AGB
  • 2,378
  • 21
  • 37
1

This is my solution

arr = location.search.replace('?', '').split('&').map(x => x.split('=')).map(x => {
    let keyName = x[0];
    let val = x[1];
    let object = {};
    object[keyName] = val;
    return object;
});

obj = {}

arr.forEach(function(x) {
    let key = Object.keys(x)[0];
    obj[key] = x[key];
});

console.log(obj);

Basicaly with location.search we obtain the right part of a url, after the path (the query params with).

location.search also returns the '?' character, replace with white space, then split whit '&', map and split with '=', for obtain un array like

[['term', 'hello'], ['lang', 'es']]

Then, assemble the object as you wanted

arr = "?safe=active&source=hp&ei=c4Q8XcOPFd3F5OUP7e242Ag&q=hola&oq=hola&gs_l=psy-ab.3..0l5j0i131j0l2j0i131j0.1324.1667..1798...1.0..0.264.744.1j3j1......0....1..gws-wiz.....10..35i39.-_FkFlX_Muw&ved=0ahUKEwiDlaTgytXjAhXdIrkGHe02DosQ4dUDCAU&uact=5".replace('?', '').split('&').map(x => x.split('=')).map(x => {
    let keyName = x[0];
    let val = x[1];
    let object = {};
    object[keyName] = val;
    return object;
});

obj = {}

arr.forEach(function(x) {
    let key = Object.keys(x)[0];
    obj[key] = x[key];
});

console.log(obj);