27

I am using the following regex to match a URL:

$search = "/([\S]+\.(MUSEUM|TRAVEL|AERO|ARPA|ASIA|COOP|INFO|NAME|BIZ|CAT|COM|INT|JOBS|NET|ORG|PRO|TEL|AC|AD|AE|AF|AG|AI|AL|AM|AN|AO|AQ|AR|AS|AT|AU|au|AW|AX|AZ|BA|BB|BD|BE|BF|BG|BH|BI|BJ|BL|BM|BN|BO|BR|BS|BT|BV|BW|BY|BZ|CA|CC|CD|CF|CG|CH|CI|CK|CL|CM|CN|CO|CR|CU|CV|CX|CY|CZ|DE|DJ|DK|DM|DO|DZ|EC|EDU|EE|EG|EH|ER|ES|ET|EU|FI|FJ|FK|FM|FO|FR|GA|GB|GD|GE|GF|GG|GH|GI|GL|GM|GN|GOV|GP|GQ|GR|GS|GT|GU|GW|GY|HK|HM|HN|HR|HT|HU|ID|IE|IL|IM|IN|IO|IQ|IR|IS|IT|JE|JM|JO|JP|KE|KG|KH|KI|KM|KN|KP|KR|KW|KY|KZ|LA|LB|LC|LI|LK|LR|LS|LT|LU|LV|LY|MA|MC|MD|ME|MF|MG|MH|MIL|MK|ML|MM|MN|MO|MOBI|MP|MQ|MR|MS|MT|MU|MV|MW|MX|MY|MZ|NA|NC|NE|NF|NG|NI|NL|NO|NP|NR|NU|NZ|OM|PA|PE|PF|PG|PH|PK|PL|PM|PN|PR|PS|PT|PW|PY|QA|RE|RO|RS|RU|RW|SA|SB|SC|SD|SE|SG|SH|SI|SJ|SK|SL|SM|SN|SO|SR|ST|SU|SV|SY|SZ|TC|TD|TF|TG|TH|TJ|TK|TL|TM|TN|TO|R|H|TP|TR|TT|TV|TW|TZ|UA|UG|UK|UM|US|UY|UZ|VA|VC|VE|VG|VI|VN|VU|WF|WS|YE|YT|YU|ZA|ZM|ZW)([\S]*))/i";

But its a bit screwed up because it also matches "example.php" which I dont want. and something like abc...test. I want it to match example.com though. and www.example.com as well as http://example.com.

It just needs a slight tweak at the end but I am not sure what. (there should be a slash after the any domain name which it is not checking for right now and it is only checking \S)

thank you for your time.

lulalala
18k15 gold badges114 silver badges179 bronze badges
asked Jul 17, 2009 at 7:32

14 Answers 14

21
$search = "#^((?#
 the scheme:
 )(?:https?://)(?#
 second level domains and beyond:
 )(?:[\S]+\.)+((?#
 top level domains:
 )MUSEUM|TRAVEL|AERO|ARPA|ASIA|EDU|GOV|MIL|MOBI|(?#
 )COOP|INFO|NAME|BIZ|CAT|COM|INT|JOBS|NET|ORG|PRO|TEL|(?#
 )A[CDEFGILMNOQRSTUWXZ]|B[ABDEFGHIJLMNORSTVWYZ]|(?#
 )C[ACDFGHIKLMNORUVXYZ]|D[EJKMOZ]|(?#
 )E[CEGHRSTU]|F[IJKMOR]|G[ABDEFGHILMNPQRSTUWY]|(?#
 )H[KMNRTU]|I[DELMNOQRST]|J[EMOP]|(?#
 )K[EGHIMNPRWYZ]|L[ABCIKRSTUVY]|M[ACDEFGHKLMNOPQRSTUVWXYZ]|(?#
 )N[ACEFGILOPRUZ]|OM|P[AEFGHKLMNRSTWY]|QA|R[EOSUW]|(?#
 )S[ABCDEGHIJKLMNORTUVYZ]|T[CDFGHJKLMNOPRTVWZ]|(?#
 )U[AGKMSYZ]|V[ACEGINU]|W[FS]|Y[ETU]|Z[AMW])(?#
 the path, can be there or not:
 )(/[a-z0-9\._/~%\-\+&\#\?!=\(\)@]*)?)$#i";

Just cleaned up a bit. This will match only HTTP(s) addresses, and, as long as you copied all top level domains correctly from IANA, only those standardized (it will not match http://localhost) and with the http:// declared.

Finally you should end with the path part, that will always start with a /, if it is there.

However, I'd suggest to follow Cerebrus: If you're not sure about this, learn regexps in a more gentle way and use proven patterns for complicated tasks.

Cheers,

By the way: Your regexp will also match something.r and something.h (between |TO| and |TR| in your example). I left them out in my version, as I guess it was a typo.

On re-reading the question: Change

 )(?:https?://)(?#

to

 )(?:https?://)?(?#

(there is a ? extra) to match 'URLs' without the scheme.

answered Jul 17, 2009 at 8:07
9
  • 1
    but i dont want the http:// in the beginning to compulsory. as i want it to match "abc.com" also. Commented Jul 17, 2009 at 8:11
  • can you please improve [\S]* to probably no spaces + only words + only numbers or whatever that is allowed in a URL? Commented Jul 17, 2009 at 10:20
  • \S should never match spaces... I updated it to what Wikipedia en.wikipedia.org/wiki/How_to_edit#Links_and_URLs allows in it's URLs. That looks reasonable. Commented Jul 17, 2009 at 10:40
  • :-) Yeah, and unfortunately all the other generic TLDs. This will make automated link detection without natural language processing near impossible... Commented Sep 9, 2011 at 8:41
  • Yeah I doubt this will catch all the open domain tlds like big.wong Commented Apr 11, 2016 at 22:37
12

Not exactly what the OP asked for but this is a much simpler regular expression that does not need to be updated each time the IANA introduces a new TLD. I believe this is more adequate for most simple needs:

^(?:https?://)?(?:[\w]+\.)(?:\.?[\w]{2,})+$

no list of TLD, localhost is not matched, the number of subparts must be>= 2 and the length of each subpart must be>= 2 (fx: "a.a" will not match but "a.ab" will match).

answered Aug 18, 2010 at 2:23
4
  • So this does not match the path & query param part of url? Commented May 31, 2013 at 3:43
  • 1
    Also fails to match hyphens in the URL. Commented Oct 28, 2014 at 16:49
  • 1
    You need to escape slashes in https?:// but still it's too broad. You can test it here: regexr.com Commented Feb 9, 2015 at 19:31
  • It doesn't seem to match subdomains e.g. consent.cookiebot.com Commented Jun 14, 2023 at 8:43
8

This question was surprisingly difficult to find an answer for. The regexes I found were too complicated to understand, and anything more that a regex is overkill and too difficult to implement.

Finally came up with:

/(\S+\.(com|net|org|edu|gov)(\/\S+)?)/

Works with http://example.com, https://example.com, example.com, http://example.com/foo.

Explanation:

  • Looks for .com, etc.
  • Matches everything before it up to the space
  • Matches everything after it up to the space
answered Jul 18, 2013 at 22:28
2
  • 1
    That will also match if a string like ".com" occurs but is not part of the domain, like in "example.zork/foo/.com/bar", and omits all the county-specific top-level domains (like .uk, .ca, etc) and others. Commented Jan 16, 2020 at 21:24
  • 1
    +1 for letting you choose which domains you'd like to accept, although I would make sure to point that out. . . adding a word boundary (\b) after the domains prevents hits that match the domain but keep extending, like example.commerce or example.governance . . /(\S+\.(com|net|org|edu|gov)\b(\/\S+)?)/ Commented Jan 6, 2023 at 15:58
6

This will get any url in its entirety, including ?= and #/ if they exist:

/[A-Za-z]+:\/\/[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_:%&;\?\#\/.=]+/g
Sebastián Palma
33.6k6 gold badges45 silver badges65 bronze badges
answered Jul 29, 2015 at 15:01
2
  • Also matches hap://foo.com/ :) Commented Aug 11, 2018 at 10:02
  • This omits a few permitted characters, such as apostrophe, !, double-quote, and plus; and % should only be allowed if followed by 2 hex digits. Not to mention internationalized URIS (IRIs)/. Commented Jan 16, 2020 at 21:13
1

Using a single regexp to match an URL string makes the code incredible unreadable. I'd suggest to use parse_url to split the URL into its components (which is not a trivial task), and check each part with a regexp.

answered Jul 17, 2009 at 7:39
1

Changing the end of the regex to (/\S*)?)$ should solve your problem.

To explain what that is doing -

  • it is looking for / followed by some characters (not whitespace)
  • this match is optional, ? indicated 0 or 1 times
  • and finally it should be followed by a end of string (or change it to \b for matching on a word boundary).
axel22
32.4k10 gold badges127 silver badges139 bronze badges
answered Jul 17, 2009 at 7:45
1

I think this is simple and efficient /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/

answered Nov 5, 2013 at 0:52
0

$ : The dollar signifies the end of the string.
For example \d*$ will match strings which end with a digit. So you need to add the $!

answered Jul 17, 2009 at 7:51
0

Regex to match all urls (with www, without www, with http or https, without http or https, includes all 2-6 letter top level domain names [for countries, ex 'ly','us'], ports, query strings, and anchors ['#']). It's not 100% but it is better than anything I have seen posted on the web.

It uses the top level domains from the first answer, combined with other techniques found in my searches. It will return any valid url that has bounds, that is where \b comes into play. Since the trailing '/' is also triggered by \b, the last one, is a match for one or more '?'.

/\b((http(s?):\/\/)?([a-z0-9\-]+\.)+(MUSEUM|TRAVEL|AERO|ARPA|ASIA|EDU|GOV|MIL|MOBI|COOP|INFO|NAME|BIZ|CAT|COM|INT|JOBS|NET|ORG|PRO|TEL|A[CDEFGILMNOQRSTUWXZ]|B[ABDEFGHIJLMNORSTVWYZ]|C[ACDFGHIKLMNORUVXYZ]|D[EJKMOZ]|E[CEGHRSTU]|F[IJKMOR]|G[ABDEFGHILMNPQRSTUWY]|H[KMNRTU]|I[DELMNOQRST]|J[EMOP]|K[EGHIMNPRWYZ]|L[ABCIKRSTUVY]|M[ACDEFGHKLMNOPQRSTUVWXYZ]|N[ACEFGILOPRUZ]|OM|P[AEFGHKLMNRSTWY]|QA|R[EOSUW]|S[ABCDEGHIJKLMNORTUVYZ]|T[CDFGHJKLMNOPRTVWZ]|U[AGKMSYZ]|V[ACEGINU]|W[FS]|Y[ETU]|Z[AMW])(:[0-9]{1,5})?((\/([a-z0-9_\-\.~]*)*)?((\/)?\?[a-z0-9+_\-\.%=&]*)?)?(#[a-zA-Z0-9!$&'()*+.=-_~:@/?]*)?)/gi
answered Feb 18, 2013 at 12:10
2
  • What does "/?" mean near the end of the regex? Did you mean "\/?" Commented Apr 1, 2013 at 18:15
  • Doesn't appear to work for things like "s3.amazonaws.com/plivocloud/…" Commented Apr 1, 2013 at 18:23
0

This is THE ONE:

_^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS
answered May 31, 2013 at 15:02
0

Try Regexy::Web::Url

r = Regexy::Web::Url.new # matches 'http://foo.com', 'www.foo.com' and 'foo.com'

answered Mar 14, 2015 at 6:05
-1
[ftp:\/\/www\/.-https:\/\/-http:\/\/][a-zA-Z0-9u00a1-uffff0]{1,3}[^ ]{1,1000} 

This works fine for me in js

var regex = new RegExp('[ftp:\/\/www\/.-https:\/\/-http:\/\/][a-zA-Z0-9u00a1-uffff0]{1,3}[^ ]{1,1000}');
regex.exec('https://www.youtube.com/watch?v=FM7MFYoylVs&feature=youtu.be&t=20s');
Christoph
51.4k21 gold badges102 silver badges129 bronze badges
answered Apr 25, 2017 at 9:42
1
  • 1
    can you format your answer better? It's very difficult to understand. Commented Apr 25, 2017 at 10:35
-2

Just to add to things. I know this doesn't fully and directly answer this specific question, but it's the best place I can find to add this info. I wrote a jQuery plug a while back to match urls for similar purpose, however at current state (will update it as time goes on) it will still consider addresses like 'http://abc.php' as valid. However, if there is no http, https, or ftp at url start, it will not return 'valid'. Though I should clarify, this jQuery method returns an object and not just one string or boolean. The object breaks things down and among the breakdown is a .valid boolean. See the full fiddle and test in the link at bottom. If you simply wanna grab the plugin and go, see below:

jQuery Plugin

(function($){$.matchUrl||$.extend({matchUrl:function(c){var b=void 0,d="url,,scheme,,authority,path,,query,,fragment".split(","),e=/^(([^\:\/\?\#]+)\:)?(\/\/([^\/\?\#]*))?([^\?\#]*)(\?([^\#]*))?(\#(.*))?/,a={url:void 0,scheme:void 0,authority:void 0,path:void 0,query:void 0,fragment:void 0,valid:!1};"string"===typeof c&&""!=c&&(b=c.match(e));if("object"===typeof b)for(x in b)d[x]&&""!=d[x]&&(a[d[x]]=b[x]);a.scheme&&a.authority&&(a.valid=!0);return a}});})(jQuery);

jsFiddle with example:

http://jsfiddle.net/SpYk3/e4Ank/

answered Jul 25, 2012 at 19:21
-3

(http|www)\S+

Just use this regex to match all url's

axel22
32.4k10 gold badges127 silver badges139 bronze badges
answered Aug 22, 2011 at 9:58
1
  • 10
    This is a really bad regular expression. I can't believe people actually voted for it. It is bad because it will also match completely invalid httpcheese as a valid url. Commented Nov 15, 2012 at 20:59

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.