Regex for a URL

/^https?:\/\/[^\s/$.?#].[^\s]*$/i

/^https?:\/\/[^\s/$.?#].[^\s]*$/i accepts a web address that starts with http:// or https://, has a host that doesn’t begin with /, $, ., ? or #, and contains no spaces anywhere. The i flag lets HTTPS:// through, as browsers do.

What it accepts

The tester below runs it with g and m over one URL per line; to check a single value, keep only i.

https://quackyard.com                  matches
http://example.com/path?q=regex#top    matches
HTTPS://sub.example.co.uk:8080/a/b     matches
ftp://example.com/file                 no: only http and https
https://                               no: no host
example.com                            no: no scheme
http://exa mple.com                    no: a space

What it misses

The pattern checks the outline of a URL, not its parts. It accepts http://localhost, http://999.1.1.1 and hosts with characters no domain can hold, and it rejects a one-letter host such as https://a, because it wants at least two characters after //. That’s the usual trade: a URL regex either turns away valid addresses or lets odd ones in.

The better test: new URL()

JavaScript ships a real URL parser, the same one the browser uses for links:

function isWebUrl(text) {
  try {
    const url = new URL(text);
    return url.protocol === 'http:' || url.protocol === 'https:';
  } catch {
    return false;
  }
}

new URL() throws on anything it can’t parse, such as http://exa mple.com, and on success hands you hostname, pathname and searchParams to check further. URL.canParse(text) gives the yes or no without the try, in Chrome 120, Firefox 115, Safari 17 and Node 18.17 or later.

Finding URLs inside text

To pull links out of a paragraph rather than check one, drop the anchors and stop at characters that usually end a link:

const links = text.match(/https?:\/\/[^\s<>"]+/g) ?? [];

A link at the end of a sentence still picks up its period or closing parenthesis, so trim those off each result: link.replace(/[.,)]+$/, '').

Try it in the Regex Tester

Flags

3 matches

Matches

#MatchAtGroups
1https://quackyard.com0–21none
2http://example.com/path?q=regex#top22–57none
3HTTPS://sub.example.co.uk:8080/a/b58–92none

What the pattern means

  • ^The start of a line
  • httpThe text "http", in any case
  • s?The character "s", in any case, optional (tried before skipping it)
  • :\/\/The text "://"
  • [^\s/$.?#]Any one character except whitespace, "/", "$", ".", "?" or "#"
    • \sA whitespace character (space, tab, line break or another Unicode space)
    • /The character "/"
    • $The character "$"
    • .The character "."
    • ?The character "?"
    • #The character "#"
  • .Any character except a line break
  • [^\s]*Any one character except whitespace, zero or more times, as many times as possible (greedy)
  • $The end of a line
  • g global: Find every match, not just the first. exec() and test() carry on from lastIndex.
  • i ignoreCase: Letters match in either case.
  • m multiline: ^ and $ match at the start and end of each line, not just of the whole string.

Runs in your browser. Nothing you enter is sent anywhere.