519

I would like to take a string

var a = "http://example.com/aa/bb/"

and process it into an object such that

a.hostname == "example.com"

and

a.pathname == "/aa/bb"
3
  • 14
    In case you're working on the current URL, you can access hostname and pathname directly from the location object.
    – rvighne
    Commented Jun 26, 2014 at 14:54
  • 1
    what about "lastPathPart"?
    – Victor
    Commented Nov 30, 2018 at 15:00
  • Not regex but the Python Module tldextract does this exactly: github.com/john-kurkowski/tldextract Commented May 15, 2019 at 0:20

26 Answers 26

625

The modern way:

new URL("http://example.com/aa/bb/")

Returns an object with properties hostname and pathname, along with a few others, most notably, port and searchParams (prepared instance of URLSearchParams).

Note that host contains both hostname+port,
but hostname only contains the domain (and not the port).

The first argument is a relative or absolute URL; if it's relative, then you need to specify the second argument (the base URL). For example, for a URL relative to the current page:

new URL("/aa/bb/", location)

In addition to browsers, this API is also available in Node.js since v7, through require('url').URL.

14
  • 62
    Experimental technology: IE doens't support this! developer.mozilla.org/en-US/docs/Web/API/URL/…
    – cwouter
    Commented Mar 18, 2015 at 15:08
  • 14
    @cwouter: It does work in Edge however, which replaces IE
    – rvighne
    Commented Jun 24, 2016 at 20:35
  • 4
    this is the way to do it, edge is already 3 versions on top of ie so it doesn't matter Commented Aug 24, 2016 at 19:27
  • 4
    @justingordon: The URL class is a Web standard, so non-browsers aren't required to implement it. However, recent versions of Nodejs do provide an identical library, require('url').URL
    – rvighne
    Commented May 19, 2017 at 4:25
  • 15
    The fact that JavaScript doesn't have a built-in way to parse URLs that works on browsers or servers is pretty sad...
    – Skitterm
    Commented Apr 25, 2018 at 0:24
384
var getLocation = function(href) {
    var l = document.createElement("a");
    l.href = href;
    return l;
};
var l = getLocation("http://example.com/path");
console.debug(l.hostname)
>> "example.com"
console.debug(l.pathname)
>> "/path"
18
  • 15
    Are you sure this is a cross-browser compatible solution?
    – cllpse
    Commented Apr 10, 2009 at 9:55
  • 76
    It should be noted that, while this may help/answer the original poster, this answer will only work for people doing JS work in a browser, since it relies on the DOM to do its work. Commented Aug 1, 2009 at 22:21
  • 5
    Another example of simplicity, alongside ingenuity. Commented Feb 21, 2012 at 13:50
  • 28
    Does not work in IE if the href is relative. l.hostname will be empty. If you're only providing full URL's then this will work. Commented Sep 6, 2012 at 18:21
  • 7
    Even with absolute URLs, IE (tested in IE 11) behaves differently from Chrome and Firefox. IE's pathname removes the leading slash, while the other browsers do not. So you'll end up with /path or path, depending on your browser.
    – TrueWill
    Commented Apr 9, 2015 at 19:00
334

found here: https://gist.github.com/jlong/2428561

var parser = document.createElement('a');
parser.href = "http://example.com:3000/pathname/?search=test#hash";

parser.protocol; // => "http:"
parser.host;     // => "example.com:3000"
parser.hostname; // => "example.com"
parser.port;     // => "3000"
parser.pathname; // => "/pathname/"
parser.hash;     // => "#hash"
parser.search;   // => "?search=test"
parser.origin;   // => "http://example.com:3000"
10
  • 11
    Note that if you just want to get the parsed parts of the current browser location, the 1st two lines become parser = location; and all the following lines work. Tried it in Chrome and IE9 just now.
    – Lee Meador
    Commented Apr 26, 2013 at 17:20
  • 9
    Also note that pathname doesn't include the leading slash in IE. Go figure. :D
    – nevelis
    Commented Feb 21, 2014 at 6:45
  • 3
    For IE, use "/" + parser.pathname
    – sbose
    Commented Feb 27, 2014 at 11:07
  • Warning: it will return http: even if you pass just domain.com to href (without any protocol). I wanted to use this to check if the protocol was missing, and if so I could add it, but it assumes http: so was unable to use it for this purpose.
    – ChatGPT
    Commented Oct 30, 2014 at 6:27
  • The hostname actually includes the protocol. Test on the latest version of Chrome.
    – Johann
    Commented Aug 23, 2017 at 15:47
138

Here's a simple function using a regexp that imitates the a tag behavior.

Pros

  • predictable behaviour (no cross browser issues)
  • doesn't need the DOM
  • it's really short.

Cons

  • The regexp is a bit difficult to read

-

function getLocation(href) {
    var match = href.match(/^(https?\:)\/\/(([^:\/?#]*)(?:\:([0-9]+))?)([\/]{0,1}[^?#]*)(\?[^#]*|)(#.*|)$/);
    return match && {
        href: href,
        protocol: match[1],
        host: match[2],
        hostname: match[3],
        port: match[4],
        pathname: match[5],
        search: match[6],
        hash: match[7]
    }
}

-

getLocation("http://example.com/");
/*
{
    "protocol": "http:",
    "host": "example.com",
    "hostname": "example.com",
    "port": undefined,
    "pathname": "/"
    "search": "",
    "hash": "",
}
*/

getLocation("http://example.com:3000/pathname/?search=test#hash");
/*
{
    "protocol": "http:",
    "host": "example.com:3000",
    "hostname": "example.com",
    "port": "3000",
    "pathname": "/pathname/",
    "search": "?search=test",
    "hash": "#hash"
}
*/

EDIT:

Here's a breakdown of the regular expression

var reURLInformation = new RegExp([
    '^(https?:)//', // protocol
    '(([^:/?#]*)(?::([0-9]+))?)', // host (hostname and port)
    '(/{0,1}[^?#]*)', // pathname
    '(\\?[^#]*|)', // search
    '(#.*|)$' // hash
].join(''));
var match = href.match(reURLInformation);
4
  • 4
    Doesn't work with any relative URLs. Did you follow RFC-3986 when making the regexp? > getLocation("//example.com/"); null > getLocation("/pathname/?search"); null > getLocation("/pathname/"); null > getLocation("relative"); null
    – gregers
    Commented May 7, 2014 at 8:26
  • 2
    I like how this does not use the DOM, but gregers has a good point. It would be nice if this can handle relative paths. It would require to use window.location (an a element) to fill in the blanks and adding code. In that case, the method would become hypocritical. Unless there is an alternative, not sure how this can be solved perfectly.
    – Turbo
    Commented Sep 24, 2014 at 22:11
  • Added the href key with original url, this provides consistency on that return object with the dom implementation. Commented Apr 11, 2017 at 14:29
  • 2
    If someone need to parse relative URLs here is the updated regexp: /^(?:(https?\:)\/\/)?(([^:\/?#]*)(?:\:([0-9]+))?)([\/]{0,1}[^?#]*)(\?[^#]*|)(#.*|)$/
    – shlensky
    Commented Apr 3, 2018 at 21:33
107
var loc = window.location;  // => "http://example.com:3000/pathname/?search=test#hash"

returns the currentUrl.

If you want to pass your own string as a url (doesn't work in IE11):

var loc = new URL("http://example.com:3000/pathname/?search=test#hash")

Then you can parse it like:

loc.protocol; // => "http:"
loc.host;     // => "example.com:3000"
loc.hostname; // => "example.com"
loc.port;     // => "3000"
loc.pathname; // => "/pathname/"
loc.hash;     // => "#hash"
loc.search;   // => "?search=test"
0
66

freddiefujiwara's answer is pretty good but I also needed to support relative URLs within Internet Explorer. I came up with the following solution:

function getLocation(href) {
    var location = document.createElement("a");
    location.href = href;
    // IE doesn't populate all link properties when setting .href with a relative URL,
    // however .href will return an absolute URL which then can be used on itself
    // to populate these additional fields.
    if (location.host == "") {
      location.href = location.href;
    }
    return location;
};

Now use it to get the needed properties:

var a = getLocation('http://example.com/aa/bb/');
document.write(a.hostname);
document.write(a.pathname);

Example:

function getLocation(href) {
  var location = document.createElement("a");
  location.href = href;
  // IE doesn't populate all link properties when setting .href with a relative URL,
  // however .href will return an absolute URL which then can be used on itself
  // to populate these additional fields.
  if (location.host == "") {
    location.href = location.href;
  }
  return location;
};
var urlToParse = 'http://example.com/aa/bb/',
  a = getLocation(urlToParse);
document.write('Absolute URL: ' + urlToParse);
document.write('<br />');
document.write('Hostname: ' + a.hostname);
document.write('<br />');
document.write('Pathname: ' + a.pathname);

5
  • 4
    This should be the accepted answer. Very clever use of relative-to-absolute URL handling. +1
    – L0j1k
    Commented May 30, 2014 at 16:52
  • Apparently not the first time a JSFiddle link died: stackoverflow.com/questions/25179964/…
    – Claus
    Commented Feb 4, 2016 at 3:55
  • 3
    This worked great, however I had one update that I hope will help others. I'm using this to check origin on a postMessage request and when the port is a default port (80 or 443), it doesn't get appended to the path. I conditionally checked for that when creating my URL: var locationHost = (location.port !== '80' && location.port !== '443') ? location.host : location.hostname; var locationOrigin = location.protocol + '//' + locationHost; Commented Apr 7, 2016 at 22:58
  • 3
    I made this comment elsewhere on a more popular variant of this solution, but as this was my favorite solution, I wanted to repeat it here. In IE11, having a username in the href will cause all these property reads to throw security errors. Example: "example.com" will work just fine. But "[email protected]" or "username:[email protected]" will make any attempt to reference one of the other properties of the anchor element (example: hash) to fail and throw an obnoxious error.
    – Clippy
    Commented Oct 17, 2016 at 4:42
  • fantastic solution! 👏🏻 Commented Aug 12, 2021 at 11:32
18

js-uri (available on Google Code) takes a string URL and resolves a URI object from it:

var some_uri = new URI("http://www.example.com/foo/bar");

alert(some_uri.authority); // www.example.com
alert(some_uri);           // http://www.example.com/foo/bar

var blah      = new URI("blah");
var blah_full = blah.resolve(some_uri);
alert(blah_full);         // http://www.example.com/foo/blah
7
  • thanks!!! but I want to uri = new Location("example.com/aa/bb") typeof(window.location) == typeof(uri) Commented Apr 10, 2009 at 2:30
  • Since window.location is a string, I don't really see how that would be possible or helpful. Why do the types need to match when you can easily convert from one to the other?
    – Rex M
    Commented Apr 10, 2009 at 2:33
  • developer.mozilla.org/en/DOM/window.location is very nice api!! so I hope convert String to window.location object Commented Apr 10, 2009 at 2:48
  • 1
    Setting window.location changes the browser so it is not going to happen. Commented Apr 10, 2009 at 3:06
  • 1
    Hmm that's right. window.location is not a string, but can be assigned from a string. I'm not sure if that can be mimicked, I've tried assigning the prototype of location to a new uri object but that did not work.
    – Rex M
    Commented Apr 10, 2009 at 3:53
15

today I meet this problem and I found: URL - MDN Web APIs

var url = new URL("http://test.example.com/dir/subdir/file.html#hash");

This return:

{ hash:"#hash", host:"test.example.com", hostname:"test.example.com", href:"http://test.example.com/dir/subdir/file.html#hash", origin:"http://test.example.com", password:"", pathname:"/dir/subdir/file.html", port:"", protocol:"http:", search: "", username: "" }

Hoping my first contribution helps you !

3
  • Duplicate answer Commented Feb 1, 2018 at 12:58
  • 9
    Yeah but the guy at the top just update his awser in 2017, me I post it in 2016.
    – A. Moynet
    Commented Apr 24, 2018 at 17:17
  • Ah my bad, sorry Commented Apr 25, 2018 at 11:01
13

What about simple regular expression?

url = "http://www.example.com/path/to/somwhere";
urlParts = /^(?:\w+\:\/\/)?([^\/]+)(.*)$/.exec(url);
hostname = urlParts[1]; // www.example.com
path = urlParts[2]; // /path/to/somwhere
3
  • Try to parse something valid like //user:[email protected]/path/x?y=z and you will see why simple regular expression does not cut it. Now throw something invalid to it and it should bail out in predictable way, too. Commented Oct 2, 2019 at 5:51
  • Simple regex is for simple problems :) But it doesn't sound to me that url like this is unparsable by regex, it would just need few more tweaks. But I'd probably go for some library if I need something more complex and bulletroof though.
    – svestka
    Commented Oct 3, 2019 at 6:55
  • 1
    I agree with @svestka's comments above, but if you want a simple regex solution and have a trusted source (like I do) and no access to the DOM or URL() (as I'm using tabris.js) then a regex can be the way to go. Here's one that can handle the query string too ^(?:\w+\:\/\/)?([^\/]+)([^\?]*)\??(.*)$ Commented Oct 16, 2020 at 10:31
12
function parseUrl(url) {
    var m = (url || sp.targetUrl()).match(/^(([^:\/?#]+:)?(?:\/\/((?:([^\/?#:]*)(?::([^\/?#:]*))?@)?([^\/?#:]*)(?::([^\/?#:]*))?)))?([^?#]*)(\?[^#]*)?(#.*)?$/),
        r = {
            hash: m[10] || "",                   // #asd
            host: m[3] || "",                    // localhost:257
            hostname: m[6] || "",                // localhost
            href: m[0] || "",                    // http://username:password@localhost:257/deploy/?asd=asd#asd
            origin: m[1] || "",                  // http://username:password@localhost:257
            pathname: m[8] || (m[1] ? "/" : ""), // /deploy/
            port: m[7] || "",                    // 257
            protocol: m[2] || "",                // http:
            search: m[9] || "",                  // ?asd=asd
            username: m[4] || "",                // username
            password: m[5] || ""                 // password
        };
    if (r.protocol.length == 2) {
        r.protocol = "file:///" + r.protocol.toUpperCase();
        r.origin = r.protocol + "//" + r.host;
    }
    r.href = r.origin + r.pathname + r.search + r.hash;
    return r;
};
parseUrl("http://username:password@localhost:257/deploy/?asd=asd#asd");

It works with both absolute and relative urls.
To handle relative path as absolute url without schema change regex to /^((?:([^:\/?#]+:)(?:\/\/))?((?:([^\/?#:]*)(?::([^\/?#:]*))?@)?([^\/?#:]*)(?::([^\/?#:]*))?))?([^?#]*)(\?[^#]*)?(#.*)?$/

9
  • abc://username:[email protected]:123/path/data?key=value&key2=value2#fragid1 Commented Dec 3, 2018 at 6:53
  • @山茶树和葡萄树 I have updated the code to handle userinfo subcomponent properly. Thanks for your comment, I didn't notice that problem before
    – Nikolay
    Commented Dec 4, 2018 at 10:40
  • love this regex
    – Kunal
    Commented Jul 12, 2019 at 19:06
  • 1
    @MichaelMao That's because absolute urls should always have scheme defined. Anyway I've updated regexp to handle such pseudo-absolute urls, so this is not a problem now. I have no enough time to test this regexp using wide range of urls, but I believe all should works fine.
    – Nikolay
    Commented Feb 13, 2022 at 17:02
  • 1
    @Brett I've updated the code and it should work fine now
    – Nikolay
    Commented Mar 28, 2023 at 18:08
10

Here is a version that I copied from https://gist.github.com/1847816, but rewritten so it's easier to read and debug. The purpose of copying the of the anchor data to another variable named "result" is because the anchor data is pretty long, and so copying a limited number of values to the result will help simplify the result.

/**
 * See: https://gist.github.com/1847816
 * Parse a URI, returning an object similar to Location
 * Usage: var uri = parseUri("hello?search#hash")
 */
function parseUri(url) {

  var result = {};

  var anchor = document.createElement('a');
  anchor.href = url;

  var keys = 'protocol hostname host pathname port search hash href'.split(' ');
  for (var keyIndex in keys) {
    var currentKey = keys[keyIndex]; 
    result[currentKey] = anchor[currentKey];
  }

  result.toString = function() { return anchor.href; };
  result.requestUri = result.pathname + result.search;  
  return result;

}
7

Cross-browser URL parsing, works around the relative path problem for IE 6, 7, 8 and 9:

function ParsedUrl(url) {
    var parser = document.createElement("a");
    parser.href = url;

    // IE 8 and 9 dont load the attributes "protocol" and "host" in case the source URL
    // is just a pathname, that is, "/example" and not "http://domain.com/example".
    parser.href = parser.href;

    // IE 7 and 6 wont load "protocol" and "host" even with the above workaround,
    // so we take the protocol/host from window.location and place them manually
    if (parser.host === "") {
        var newProtocolAndHost = window.location.protocol + "//" + window.location.host;
        if (url.charAt(1) === "/") {
            parser.href = newProtocolAndHost + url;
        } else {
            // the regex gets everything up to the last "/"
            // /path/takesEverythingUpToAndIncludingTheLastForwardSlash/thisIsIgnored
            // "/" is inserted before because IE takes it of from pathname
            var currentFolder = ("/"+parser.pathname).match(/.*\//)[0];
            parser.href = newProtocolAndHost + currentFolder + url;
        }
    }

    // copies all the properties to this object
    var properties = ['host', 'hostname', 'hash', 'href', 'port', 'protocol', 'search'];
    for (var i = 0, n = properties.length; i < n; i++) {
      this[properties[i]] = parser[properties[i]];
    }

    // pathname is special because IE takes the "/" of the starting of pathname
    this.pathname = (parser.pathname.charAt(0) !== "/" ? "/" : "") + parser.pathname;
}

Usage (demo JSFiddle here):

var myUrl = new ParsedUrl("http://www.example.com:8080/path?query=123#fragment");

Result:

{
    hash: "#fragment"
    host: "www.example.com:8080"
    hostname: "www.example.com"
    href: "http://www.example.com:8080/path?query=123#fragment"
    pathname: "/path"
    port: "8080"
    protocol: "http:"
    search: "?query=123"
}
5

For those looking for a modern solution that works in IE, Firefox, AND Chrome:

None of these solutions that use a hyperlink element will work the same in chrome. If you pass an invalid (or blank) url to chrome, it will always return the host where the script is called from. So in IE you will get blank, whereas in Chrome you will get localhost (or whatever).

If you are trying to look at the referrer, this is deceitful. You will want to make sure that the host you get back was in the original url to deal with this:

    function getHostNameFromUrl(url) {
        // <summary>Parses the domain/host from a given url.</summary>
        var a = document.createElement("a");
        a.href = url;

        // Handle chrome which will default to domain where script is called from if invalid
        return url.indexOf(a.hostname) != -1 ? a.hostname : '';
    }
2
  • This is a very important thing to consider!
    – 2rs2ts
    Commented Dec 31, 2013 at 14:58
  • This completely breaks relative urls, though!
    – lakenen
    Commented Jun 10, 2014 at 20:23
4

The AngularJS way - fiddle here: http://jsfiddle.net/PT5BG/4/

<!DOCTYPE html>
<html>
<head>
    <title>Parse URL using AngularJS</title>
</head>
<body ng-app ng-controller="AppCtrl" ng-init="init()">

<h3>Parse URL using AngularJS</h3>

url: <input type="text" ng-model="url" value="" style="width:780px;">

<ul>
    <li>href = {{parser.href}}</li>
    <li>protocol = {{parser.protocol}}</li>
    <li>host = {{parser.host}}</li>
    <li>hostname = {{parser.hostname}}</li>
    <li>port = {{parser.port}}</li>
    <li>pathname = {{parser.pathname}}</li>
    <li>hash = {{parser.hash}}</li>
    <li>search = {{parser.search}}</li>
</ul>

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js"></script>

<script>
function AppCtrl($scope) {

    $scope.$watch('url', function() {
        $scope.parser.href = $scope.url;
    });

    $scope.init = function() {
        $scope.parser = document.createElement('a');
        $scope.url = window.location;
    }

}
</script>

</body>
</html>
1
  • 2
    It will be more angular if you will use $document and $window services Commented Sep 28, 2014 at 6:26
4

Expanded on acdcjunior solution by adding "searchParam" function
Mimicking the URL object, added "searchParam" to parse query string
Works for IE 6, 7, 8 9, 10, 11

USAGE - (JSFiddle Link)

// USAGE:
var myUrl = new ParsedUrl("http://www.example.com/path?var1=123&var2=abc#fragment");
console.log(myUrl);
console.log(myUrl.searchParam('var1'));
console.log(myUrl.searchParam('var2'));

OUTPUT - (JSFiddle Link)

{
  hash: "#fragment",
  host: "www.example.com:8080",
  hostname: "www.example.com",
  href: "http://www.example.com:8080/path?var1=123&amp;var2=abc#fragment",
  pathname: "/path",
  port: "80",
  protocol: "http:",
  search: "?var1=123&amp;var2=abc"
}

"123"
"abc"

CODE - (JSFiddle Link)

function ParsedUrl(url) {
    var parser = document.createElement("a");
    parser.href = url;
    
    // IE 8 and 9 dont load the attributes "protocol" and "host" in case the source URL
    // is just a pathname, that is, "/example" and not "http://www.example.com/example".
    parser.href = parser.href;
    
    // IE 7 and 6 wont load "protocol" and "host" even with the above workaround,
    // so we take the protocol/host from window.location and place them manually
    if (parser.host === "") {
        var newProtocolAndHost = window.location.protocol + "//" + window.location.host;
        if (url.charAt(1) === "/") {
            parser.href = newProtocolAndHost + url;
        } else {
            // the regex gets everything up to the last "/"
            // /path/takesEverythingUpToAndIncludingTheLastForwardSlash/thisIsIgnored
            // "/" is inserted before because IE takes it of from pathname
            var currentFolder = ("/"+parser.pathname).match(/.*\//)[0];
            parser.href = newProtocolAndHost + currentFolder + url;
        }
    }
    
    // copies all the properties to this object
    var properties = ['host', 'hostname', 'hash', 'href', 'port', 'protocol', 'search'];
    for (var i = 0, n = properties.length; i < n; i++) {
      this[properties[i]] = parser[properties[i]];
    }
    
    // pathname is special because IE takes the "/" of the starting of pathname
    this.pathname = (parser.pathname.charAt(0) !== "/" ? "/" : "") + parser.pathname;
  
  //search Params
  this.searchParam =  function(variable) {
    var query = (this.search.indexOf('?') === 0) ? this.search.substr(1) : this.search;
    var vars = query.split('&');
    for (var i = 0; i < vars.length; i++) {
        var pair = vars[i].split('=');
        if (decodeURIComponent(pair[0]) == variable) {
            return decodeURIComponent(pair[1]);
        }
    }
    console.log('Query variable %s not found', variable);
    return '';
    };
}
1
  • 2
    2021 answer: Use new URL('your string url') and you get the same result. Commented Aug 16, 2021 at 8:06
3

Simple and robust solution using the module pattern. This includes a fix for IE where the pathname does not always have a leading forward-slash (/).

I have created a Gist along with a JSFiddle which offers a more dynamic parser. I recommend you check it out and provide feedback.

var URLParser = (function (document) {
    var PROPS = 'protocol hostname host pathname port search hash href'.split(' ');
    var self = function (url) {
        this.aEl = document.createElement('a');
        this.parse(url);
    };
    self.prototype.parse = function (url) {
        this.aEl.href = url;
        if (this.aEl.host == "") {
           this.aEl.href = this.aEl.href;
        }
        PROPS.forEach(function (prop) {
            switch (prop) {
                case 'hash':
                    this[prop] = this.aEl[prop].substr(1);
                    break;
                default:
                    this[prop] = this.aEl[prop];
            }
        }, this);
        if (this.pathname.indexOf('/') !== 0) {
            this.pathname = '/' + this.pathname;
        }
        this.requestUri = this.pathname + this.search;
    };
    self.prototype.toObj = function () {
        var obj = {};
        PROPS.forEach(function (prop) {
            obj[prop] = this[prop];
        }, this);
        obj.requestUri = this.requestUri;
        return obj;
    };
    self.prototype.toString = function () {
        return this.href;
    };
    return self;
})(document);

Demo

var URLParser = (function(document) {
  var PROPS = 'protocol hostname host pathname port search hash href'.split(' ');
  var self = function(url) {
    this.aEl = document.createElement('a');
    this.parse(url);
  };
  self.prototype.parse = function(url) {
    this.aEl.href = url;
    if (this.aEl.host == "") {
      this.aEl.href = this.aEl.href;
    }
    PROPS.forEach(function(prop) {
      switch (prop) {
        case 'hash':
          this[prop] = this.aEl[prop].substr(1);
          break;
        default:
          this[prop] = this.aEl[prop];
      }
    }, this);
    if (this.pathname.indexOf('/') !== 0) {
      this.pathname = '/' + this.pathname;
    }
    this.requestUri = this.pathname + this.search;
  };
  self.prototype.toObj = function() {
    var obj = {};
    PROPS.forEach(function(prop) {
      obj[prop] = this[prop];
    }, this);
    obj.requestUri = this.requestUri;
    return obj;
  };
  self.prototype.toString = function() {
    return this.href;
  };
  return self;
})(document);

/* Main */
var out = document.getElementById('out');
var urls = [
  'https://www.example.org:5887/foo/bar?a=1&b=2#section-1',
  'ftp://www.files.com:22/folder?id=7'
];
var parser = new URLParser();
urls.forEach(function(url) {
  parser.parse(url);
  println(out, JSON.stringify(parser.toObj(), undefined, ' '), 0, '#0000A7');
});

/* Utility functions */
function print(el, text, bgColor, fgColor) {
  var span = document.createElement('span');
  span.innerHTML = text;
  span.style['backgroundColor'] = bgColor || '#FFFFFF';
  span.style['color'] = fgColor || '#000000';
  el.appendChild(span);
}
function println(el, text, bgColor, fgColor) {
  print(el, text, bgColor, fgColor);
  el.appendChild(document.createElement('br'));
}
body {
  background: #444;
}
span {
  background-color: #fff;
  border: thin solid black;
  display: inline-block;
}
#out {
  display: block;
  font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;
  font-size: 12px;
  white-space: pre;
}
<div id="out"></div>

Output

{
 "protocol": "https:",
 "hostname": "www.example.org",
 "host": "www.example.org:5887",
 "pathname": "/foo/bar",
 "port": "5887",
 "search": "?a=1&b=2",
 "hash": "section-1",
 "href": "https://www.example.org:5887/foo/bar?a=1&b=2#section-1",
 "requestUri": "/foo/bar?a=1&b=2"
}
{
 "protocol": "ftp:",
 "hostname": "www.files.com",
 "host": "www.files.com:22",
 "pathname": "/folder",
 "port": "22",
 "search": "?id=7",
 "hash": "",
 "href": "ftp://www.files.com:22/folder?id=7",
 "requestUri": "/folder?id=7"
}
3

Use https://www.npmjs.com/package/uri-parse-lib for this

var t = parserURI("http://user:[email protected]:8080/directory/file.ext?query=1&next=4&sed=5#anchor");
3

Why do not use it?

        $scope.get_location=function(url_str){
        var parser = document.createElement('a');
        parser.href =url_str;//"http://example.com:3000/pathname/?search=test#hash";
        var info={
            protocol:parser.protocol,   
            hostname:parser.hostname, // => "example.com"
            port:parser.port,     // => "3000"
            pathname:parser.pathname, // => "/pathname/"
            search:parser.search,   // => "?search=test"
            hash:parser.hash,     // => "#hash"
            host:parser.host, // => "example.com:3000"      
        }
        return info;
    }
    alert( JSON.stringify( $scope.get_location("http://localhost:257/index.php/deploy/?asd=asd#asd"),null,4 ) );
3

You can also use parse_url() function from Locutus project (former php.js).

Code:

parse_url('http://username:password@hostname/path?arg=value#anchor');

Result:

{
  scheme: 'http',
  host: 'hostname',
  user: 'username',
  pass: 'password',
  path: '/path',
  query: 'arg=value',
  fragment: 'anchor'
}
2
2

Stop reinventing the wheel. Use https://github.com/medialize/URI.js/

var uri = new URI("http://example.org:80/foo/hello.html");
// get host
uri.host(); // returns string "example.org:80"
// set host
uri.host("example.org:80");
4
  • 6
    Because every time you want to solve a problem... use a library? Okay... (not)
    – jiminikiz
    Commented Sep 29, 2015 at 22:44
  • 4
    Not always (actually almost never) but URLs are very tricky to parse, there are many many details in the RFCs. Better to use a library that has been used and tested by thousands. Commented Oct 4, 2015 at 22:12
  • 1
    How about just use what is built in, instead of having someone else reinvent the wheel with a library? See stackoverflow.com/a/24006120/747739
    – Phil
    Commented Jan 31, 2019 at 20:52
  • There is no IE11 support for the built-in function, so this library is excellent. To say never to use a library is like saying we should never have used jQuery and just write native code, which is absolutely ridiculous. Every developer has a different use case, there is no 'best' way, sometimes vanilla/native works best, sometimes it doesn't... something 92% of developers still has to learn.
    – tno2007
    Commented Mar 4, 2020 at 11:58
1

Just use url.js library (for web and node.js).

https://github.com/websanova/js-url

url: http://example.com?param=test#param=again

url('?param'); // test
url('#param'); // again
url('protocol'); // http
url('port'); // 80
url('domain'); // example.com
url('tld'); // com

etc...
1

a simple hack with the first answer

var getLocation = function(href=window.location.href) {
    var l = document.createElement("a");
    l.href = href;
    return l;
};

this can used even without argument to figure out the current hostname getLocation().hostname will give current hostname

0

This doesn't parse the query and hash, but otherwise it works well otherwise.

const getURIParts = (url) => {
  const matches = url.match(/^(\w+?:\/\/)?([\w-\.]+(?=\/?))?:?(\d*)?([^:]*)/)
  return {
    scheme: matches ? matches[1] : undefined,
    host: matches ? matches[2] : '',
    port: matches ? matches[3] : undefined,
    pathname: matches ? matches[4] : ''
  }
}

console.log(getURIParts(""))
console.log(getURIParts("http://localhost/bla"))
console.log(getURIParts("https://api.spotify.com/"))
console.log(getURIParts("https://api.spotify.com"))
console.log(getURIParts("wss://wss.slack.com/link/?ticket=1234-5678"))
console.log(getURIParts("localhost"))
console.log(getURIParts("localhost/bla"))
console.log(getURIParts("localhost/"))
console.log(getURIParts("api.spotify.com/bla/two"))
console.log(getURIParts("api.spotify.com:8000/bla/two"))
console.log(getURIParts("https://api.spotify.com:8800/"))
console.log(getURIParts("/mp3-preview/f504e6b8e037771318656394f532dede4f9bcaea"))

0

Of course in >2016 the right answer is using URL API
For page URL window.location
And for <a href="..."> HTMLAnchorElement API

Also for supporting older browser, using polyfill:

<script crossorigin="anonymous" src="https://polyfill.io/v3/polyfill.min.js?features=URL"></script>

But just as an other option, it can be handle easy and accurate by RegEx pattern:

function URIinfo(s) {
    s=s.match(/^(([^/]*?:)\/*((?:([^:]+):([^@]+)@)?([^/:]{2,}|\[[\w:]+])(:\d*)?(?=\/|$))?)?((.*?\/)?(([^/]*?)(\.[^/.]+?)?))(\?.*?)?(#.*)?$/);
    return {origin:s[1],protocol:s[2],host:s[3],username:s[4],password:s[5],hostname:s[6],port:s[7],path:s[8],folders:s[9],file:s[10],filename:s[11],fileext:s[12],search:s[13],hash:s[14]};
}

var sample='http://user:[email protected]:8080/onefolder/folder.name/file.min.js?query=http://my.site.com:8080/file.exe#hash-root:/file/1.txt';

console.log (URIinfo(sample));
/*
{
  "origin": "http://user:[email protected]:8080",
  "protocol": "http:",
  "host": "user:[email protected]:8080",
  "username": "user",
  "password": "password",
  "hostname": "my.site.com",
  "port": ":8080",
  "path": "/onefolder/folder.name/file.min.js",
  "folders": "/onefolder/folder.name/",
  "file": "file.min.js",
  "filename": "file.min",
  "fileext": ".js",
  "search": "?query=http://my.site.com:8080/file.exe",
  "hash": "#hash-root:/file/1.txt"
}
*/

Work with the RegEx

It is fine with any kind of

  • Absolute / Relative paths
  • IPv4 / IPv6
  • Net protocols / Local Files
  • Query / Hash

And will return all URL options but not searchParams

(+) Also will return file info like PHP pathInfo

0

How about?

'https://stackoverflow.com/questions/736513/how-do-i-parse-a-url-into-hostname-and-path-in-javascript'.split('//').pop().split('/')[0]

Resulting:

'stackoverflow.com'

-1

Try This :

function getUrlPath(str){
//fakepath when url not have a path
  var fakepath = "/FakPath";
  var url = str+fakepath;
  var reg = /.+?\:\/\/.+?(\/.+?)(?:#|\?|$)/;
  var output = reg.exec(url);
  // check "output" != null
  return (output) ? output[1].replace(fakepath,"") : fakepath;
}

var myurl = "https://stackoverflow.com/questions/736513/";
const path = getUrlPath(myurl);

console.log(   path     );
//output :  /questions/736513/

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