Categories
javascript plugins query-string url

How can I get query string values in JavaScript?

2695

Is there a plugin-less way of retrieving query string values via jQuery (or without)?

If so, how? If not, is there a plugin which can do so?

6

  • I use the plugin getUrlParam described in jQuery-Plugin – getUrlParam (version 2).

    – coma

    May 23, 2009 at 8:19


  • 69

    A plain javascript solution without RegEx: css-tricks.com/snippets/javascript/get-url-variables

    Oct 29, 2012 at 14:50


  • 6

    Although the top solution to the question deserves its popularity because of its excellent observation that jQuery is not needed, its method of creating new regular expressions and re-parsing the query string for every parameter desired is extremely inefficient. Far more efficient (and versatile) solutions have been in existence for a long time, for example within this article reprinted here: htmlgoodies.com/beyond/javascript/article.php/11877_3755006_3/…

    May 14, 2013 at 6:00


  • 1

    possible duplicate of JavaScript query string

    – user456814

    Jul 31, 2013 at 23:09

  • 4

    Joseph, the “excellent observation that jQuery is not needed”? Of course it’s not needed. Everything jQuery does, it does using JavaScript. People don’t use jQuery because it does stuff that JavaScript can’t do. The point of jQuery is convenience.

    May 30, 2014 at 1:12

9823

Update: Jan-2022

Using Proxy() is more performant than using Object.fromEntries() and better supported

const params = new Proxy(new URLSearchParams(window.location.search), {
  get: (searchParams, prop) => searchParams.get(prop),
});
// Get the value of "some_key" in eg "https://example.com/?some_key=some_value"
let value = params.some_key; // "some_value"

Update: June-2021

For a specific case when you need all query params:

const urlSearchParams = new URLSearchParams(window.location.search);
const params = Object.fromEntries(urlSearchParams.entries());

Update: Sep-2018

You can use URLSearchParams which is simple and has decent (but not complete) browser support.

const urlParams = new URLSearchParams(window.location.search);
const myParam = urlParams.get('myParam');

Original

You don’t need jQuery for that purpose. You can use just some pure JavaScript:

function getParameterByName(name, url = window.location.href) {
    name = name.replace(/[\[\]]/g, '\\$&');
    var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
        results = regex.exec(url);
    if (!results) return null;
    if (!results[2]) return '';
    return decodeURIComponent(results[2].replace(/\+/g, ' '));
}

Usage:

// query string: ?foo=lorem&bar=&baz
var foo = getParameterByName('foo'); // "lorem"
var bar = getParameterByName('bar'); // "" (present with empty value)
var baz = getParameterByName('baz'); // "" (present with no value)
var qux = getParameterByName('qux'); // null (absent)

NOTE: If a parameter is present several times (?foo=lorem&foo=ipsum), you will get the first value (lorem). There is no standard about this and usages vary, see for example this question: Authoritative position of duplicate HTTP GET query keys.

NOTE: The function is case-sensitive. If you prefer case-insensitive parameter name, add ‘i’ modifier to RegExp

NOTE: If you’re getting a no-useless-escape eslint error, you can replace name = name.replace(/[\[\]]/g, '\\$&'); with name = name.replace(/[[\]]/g, '\\$&').


This is an update based on the new URLSearchParams specs to achieve the same result more succinctly. See answer titled “URLSearchParams” below.

14

  • I notice that Object.fromEntries(urlSearchParams) yields the same result. So we don’t actually need the .entries()

    Oct 27, 2021 at 6:33


  • 2

    June-2021 and Proxy solutions don’t work with SPA (Singla Page Application). SPA changes de content of the page and can even change the URL relative path (adding query strings for example).

    – shimatai

    Feb 4 at 18:55

  • How can you iterate over the values ​​dynamically, with that Proxy structure?

    – DMA VE

    Feb 22 at 15:55

  • 1

    @JeffThompson, trailing commas are allowed but not required. They make it easier for developers to add new entries to the object without having to edit any of the existing entries’ lines.

    – kaerimasu

    Apr 4 at 14:32

  • 1

    Jan-2022: if you need all values of the same parameter name as an array then use searchParams.getAll(prop).

    – andy

    Apr 6 at 19:47

1766

Some of the solutions posted here are inefficient. Repeating the regular expression search every time the script needs to access a parameter is completely unnecessary, one single function to split up the parameters into an associative-array style object is enough. If you’re not working with the HTML 5 History API, this is only necessary once per page load. The other suggestions here also fail to decode the URL correctly.

var urlParams;
(window.onpopstate = function () {
    var match,
        pl     = /\+/g,  // Regex for replacing addition symbol with a space
        search = /([^&=]+)=?([^&]*)/g,
        decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
        query  = window.location.search.substring(1);
  
    urlParams = {};
    while (match = search.exec(query))
       urlParams[decode(match[1])] = decode(match[2]);
})();

Example querystring:

?i=main&mode=front&sid=de8d49b78a85a322c4155015fdce22c4&enc=+Hello%20&empty

Result:

 urlParams = {
    enc: " Hello ",
    i: "main",
    mode: "front",
    sid: "de8d49b78a85a322c4155015fdce22c4",
    empty: ""
}

alert(urlParams["mode"]);
// -> "front"

alert("empty" in urlParams);
// -> true

This could easily be improved upon to handle array-style query strings too. An example of this is here, but since array-style parameters aren’t defined in RFC 3986 I won’t pollute this answer with the source code. For those interested in a “polluted” version, look at campbeln’s answer below.

Also, as pointed out in the comments, ; is a legal delimiter for key=value pairs. It would require a more complicated regex to handle ; or &, which I think is unnecessary because it’s rare that ; is used and I would say even more unlikely that both would be used. If you need to support ; instead of &, just swap them in the regex.


If you’re using a server-side preprocessing language, you might want to use its native JSON functions to do the heavy lifting for you. For example, in PHP you can write:

<script>var urlParams = <?php echo json_encode($_GET, JSON_HEX_TAG);?>;</script>

Much simpler!

#UPDATED

A new capability would be to retrieve repeated params as following myparam=1&myparam=2. There is not a specification, however, most of the current approaches follow the generation of an array.

myparam = ["1", "2"]

So, this is the approach to manage it:

let urlParams = {};
(window.onpopstate = function () {
    let match,
        pl = /\+/g,  // Regex for replacing addition symbol with a space
        search = /([^&=]+)=?([^&]*)/g,
        decode = function (s) {
            return decodeURIComponent(s.replace(pl, " "));
        },
        query = window.location.search.substring(1);

    while (match = search.exec(query)) {
        if (decode(match[1]) in urlParams) {
            if (!Array.isArray(urlParams[decode(match[1])])) {
                urlParams[decode(match[1])] = [urlParams[decode(match[1])]];
            }
            urlParams[decode(match[1])].push(decode(match[2]));
        } else {
            urlParams[decode(match[1])] = decode(match[2]);
        }
    }
})();

2

  • This worked like a Charm to fetch the live URL on page load every single time:-)

    Feb 2, 2021 at 13:54


  • Very nice! However, I suggest to introduce local variables let parameterKey = decode(match[1]); let parameterValue = decode(match[2]);. This makes it more obvious what is happening IMHO.

    – mihca

    Jul 7, 2021 at 6:30

1315

ES2015 (ES6)

getQueryStringParams = query => {
    return query
        ? (/^[?#]/.test(query) ? query.slice(1) : query)
            .split('&')
            .reduce((params, param) => {
                    let [key, value] = param.split('=');
                    params[key] = value ? decodeURIComponent(value.replace(/\+/g, ' ')) : '';
                    return params;
                }, {}
            )
        : {}
};

Without jQuery

var qs = (function(a) {
    if (a == "") return {};
    var b = {};
    for (var i = 0; i < a.length; ++i)
    {
        var p=a[i].split('=', 2);
        if (p.length == 1)
            b[p[0]] = "";
        else
            b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
    }
    return b;
})(window.location.search.substr(1).split('&'));

With an URL like ?topic=123&name=query+string, the following will return:

qs["topic"];    // 123
qs["name"];     // query string
qs["nothere"];  // undefined (object)

Google method

Tearing Google’s code I found the method they use: getUrlParameters

function (b) {
    var c = typeof b === "undefined";
    if (a !== h && c) return a;
    for (var d = {}, b = b || k[B][vb], e = b[p]("?"), f = b[p]("#"), b = (f === -1 ? b[Ya](e + 1) : [b[Ya](e + 1, f - e - 1), "&", b[Ya](f + 1)][K](""))[z]("&"), e = i.dd ? ia : unescape, f = 0, g = b[w]; f < g; ++f) {
        var l = b[f][p]("=");
        if (l !== -1) {
            var q = b[f][I](0, l),
                l = b[f][I](l + 1),
                l = l[Ca](/\+/g, " ");
            try {
                d[q] = e(l)
            } catch (A) {}
        }
    }
    c && (a = d);
    return d
}

It is obfuscated, but it is understandable. It does not work because some variables are undefined.

They start to look for parameters on the url from ? and also from the hash #. Then for each parameter they split in the equal sign b[f][p]("=") (which looks like indexOf, they use the position of the char to get the key/value). Having it split they check whether the parameter has a value or not, if it has then they store the value of d, otherwise they just continue.

In the end the object d is returned, handling escaping and the + sign. This object is just like mine, it has the same behavior.


My method as a jQuery plugin

(function($) {
    $.QueryString = (function(paramsArray) {
        let params = {};

        for (let i = 0; i < paramsArray.length; ++i)
        {
            let param = paramsArray[i]
                .split('=', 2);
            
            if (param.length !== 2)
                continue;
            
            params[param[0]] = decodeURIComponent(param[1].replace(/\+/g, " "));
        }
            
        return params;
    })(window.location.search.substr(1).split('&'))
})(jQuery);

Usage

//Get a param
$.QueryString.param
//-or-
$.QueryString["param"]
//This outputs something like...
//"val"

//Get all params as object
$.QueryString
//This outputs something like...
//Object { param: "val", param2: "val" }

//Set a param (only in the $.QueryString object, doesn't affect the browser's querystring)
$.QueryString.param = "newvalue"
//This doesn't output anything, it just updates the $.QueryString object

//Convert object into string suitable for url a querystring (Requires jQuery)
$.param($.QueryString)
//This outputs something like...
//"param=newvalue&param2=val"

//Update the url/querystring in the browser's location bar with the $.QueryString object
history.replaceState({}, '', "?" + $.param($.QueryString));
//-or-
history.pushState({}, '', "?" + $.param($.QueryString));

Performance test (split method against regex method) (jsPerf)

Preparation code: methods declaration

Split test code

var qs = window.GetQueryString(query);

var search = qs["q"];
var value = qs["value"];
var undef = qs["undefinedstring"];

Regex test code

var search = window.getParameterByName("q");
var value = window.getParameterByName("value");
var undef = window.getParameterByName("undefinedstring");

Testing in Firefox 4.0 x86 on Windows Server 2008 R2 / 7 x64

  • Split method: 144,780 ±2.17% fastest
  • Regex method: 13,891 ±0.85% | 90% slower

0