/^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(/[.,)]+$/, '').