Quick answer
A practical URL regex is ^https?:\/\/(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z]{2,63}(?::\d{1,5})?(?:[\/?#]\S*)?$ with the i flag. It requires http or https, a domain with a real top-level part, an optional port, and allows any path, query and fragment without spaces. For anything security-sensitive, parse with new URL() and check the protocol and hostname instead of trusting a regex.
- Tested examples
- Token-by-token breakdown
- Code in 5 languages
- Live tester
How to use the URL (http and https) regex
- 1Copy the pattern with Copy pattern in the tester, or take a ready-made snippet for your language from the code section below.
- 2Check the sample lines in Test string: every line the URL (http and https) regex accepts is highlighted, rejected lines stay plain.
- 3Paste your own values one per line to see which pass, and read Explanation for what each part of the pattern does.
- 4Open the Code tab for JavaScript, Python, Go, C#, PHP or Dart with the pattern translated and escaped.
- 5Validate again on the server: client-side checks give users quick feedback, not security.
How does the URL (http and https) regex work?
Read it left to right. Each piece below matches one part of the input:
^https?:\/\/The scheme: http or https, then ://. The slashes are escaped so the pattern also works inside /…/ literals.(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)+One or more domain labels, each 1–63 characters with no hyphen at either end, followed by a dot.[A-Za-z]{2,63}The top-level domain, letters only.(?::\d{1,5})?An optional port such as :8080.(?:[\/?#]\S*)?Optionally a path, query or fragment: anything without whitespace, starting with /, ? or #.$End of the string.
Flags: i (ignore case).
Which strings does the URL (http and https) regex match?
The whole input must match, from the first character to the last. Every row below is checked against the pattern by our automated test suite before each release.
| Input | Matches? | Why |
|---|---|---|
https://example.com | Yes | The minimum: scheme and domain. |
http://www.example.co.uk/path?q=1#top | Yes | Subdomain, path, query and fragment. |
https://api.example.io:8443/v1/users | Yes | A port and a versioned API path. |
https://example.com/search?q=regex+tester&page=2 | Yes | Query strings are free-form (no spaces). |
HTTPS://EXAMPLE.COM | Yes | Case-insensitive thanks to the i flag. |
example.com | No | No scheme. Add https:// before validating if you accept bare domains. |
ftp://example.com | No | Only http and https are accepted. |
https:// | No | No host. |
https://exa mple.com | No | Spaces are not allowed in a host. |
http://-example.com | No | Labels cannot start with a hyphen. |
https://localhost:3000 | No | No top-level domain: local hosts are rejected on purpose. |
https://192.168.0.1 | No | IP addresses are not matched; the last label must be letters. |
Should I validate URLs with a regex or the URL parser?
For form feedback, a regex is fine. For anything that will be fetched, redirected to or rendered as a link, use the platform's parser and check the parts you care about:
function isSafeHttpUrl(value) {
try {
const url = new URL(value);
return url.protocol === "https:" || url.protocol === "http:";
} catch {
return false;
}
}The parser follows the WHATWG URL Standard, the same rules the browser uses, so there is no gap between what you validate and what actually gets requested. Checking the protocol blocks javascript: links, a classic XSS vector. If your server fetches user-supplied URLs, also block private and loopback addresses to prevent server-side request forgery (SSRF): a regex cannot do that, because the hostname may resolve to an internal IP.
How do I allow localhost, IP addresses or other schemes?
Extend the host part with alternatives:
- localhost: replace the domain section with
(?:localhost|(?:label\.)+[A-Za-z]{2,63}). - IPv4 hosts: add the IPv4 pattern as another alternative.
- Other schemes: change
https?to(?:https?|ftp|wss?).
Internationalized domains (https://bücher.example) arrive in Punycode once parsed (xn--bcher-kva.example), which this pattern accepts; raw Unicode hostnames need the u flag and \p{L} classes. To percent-encode the path and query safely, use the URL encoder.
How do I use the URL (http and https) regex in JavaScript, Python, Go, C# and PHP?
The pattern is translated for each engine rather than pasted as is: named groups, anchors, escapes, shorthand classes and flags are adjusted so each snippet behaves as closely to the JavaScript version as its engine allows. Differences that remain (Go's RE2 has no lookarounds or backreferences, for example) are called out under each one. The Code tab in the tester above also exports Dart, and updates as you edit the pattern.
JavaScript and TypeScript
const regex = /^https?:\/\/(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z]{2,63}(?::\d{1,5})?(?:[\/?#]\S*)?$/i;
function isValid(value) {
return regex.test(value);
}
console.log(isValid("https://example.com"));Python
import re
pattern = re.compile(r"^https?:\/\/(?:[A-Za-z0-9](?:[A-Za-z0-9\-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z]{2,63}(?::[0-9]{1,5})?(?:[\/?#]\S*)?\Z", re.IGNORECASE)
def is_valid(value: str) -> bool:
return pattern.search(value) is not None
print(is_valid("https://example.com"))- \d and \w are written as [0-9] and [A-Za-z0-9_] because in Python they also match digits and letters from other scripts.
- JavaScript's $ only matches at the very end of the string. Python's $ also matches before a trailing newline, so the pattern uses \Z instead.
Go
package main
import (
"fmt"
"regexp"
)
func main() {
re := regexp.MustCompile(`(?i)^https?:\/\/(?:[A-Za-z0-9](?:[A-Za-z0-9\-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z]{2,63}(?::\d{1,5})?(?:[\/?#]\S*)?$`)
fmt.Println(re.MatchString("https://example.com"))
}- Go's \s only matches space, \t, \n, \f and \r; JavaScript's also matches the non-breaking space and other Unicode spaces.
C#
using System;
using System.Text.RegularExpressions;
// The timeout stops a pathological input from hanging the thread (ReDoS).
var regex = new Regex(@"^https?:\/\/(?:[A-Za-z0-9](?:[A-Za-z0-9\-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z]{2,63}(?::[0-9]{1,5})?(?:[\/?#]\S*)?\z", RegexOptions.IgnoreCase, TimeSpan.FromSeconds(1));
Console.WriteLine(regex.IsMatch("https://example.com"));- \d and \w are written as [0-9] and [A-Za-z0-9_] because in .NET they also match digits and letters from other scripts.
- JavaScript's $ only matches at the very end of the string. .NET's $ also matches before a trailing newline, so the pattern uses \z instead.
PHP
<?php
$pattern = '/^https?:\/\/(?:[A-Za-z0-9](?:[A-Za-z0-9\-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z]{2,63}(?::\d{1,5})?(?:[\/?#]\S*)?$/iD';
function isValid(string $value, string $pattern): bool
{
return preg_match($pattern, $value) === 1;
}
var_dump(isValid('https://example.com', $pattern));- PCRE's \s matches ASCII whitespace unless Unicode properties (UCP) are on; JavaScript's also matches the non-breaking space and other Unicode spaces.
- The D modifier makes $ match only at the very end, like JavaScript (PCRE's $ also matches before a trailing newline).
Which related regex patterns are useful?
- Regex for Domain Names: Hostnames with valid labels, a 253-character limit and Punycode support.
- Regex for YouTube URLs and Video IDs: Every common YouTube link format, with the 11-character video ID in a named group.
- Regex for IPv4 Addresses: Four octets from 0 to 255, no leading zeros, nothing before or after.
- Regex for URL Slugs: Lowercase letters and digits separated by single hyphens, like regex-tester.
Browse all 25 patterns in the regex pattern library, or build your own in the regex tester.
Frequently asked questions
Last updated by the Playxoft engineering team.