/^/
MediumWeb4 min read

Twitter/X URL Regex

Matches a Twitter/X profile URL or an individual tweet (status) URL on either twitter.com or x.com, capturing the handle and optional tweet ID.

#url#twitter#x#web#validation#social

Regex Pattern

^https?:\/\/(?:www\.)?(?:twitter|x)\.com\/(\w{1,15})(?:\/status\/(\d+))?\/?$

Pattern Breakdown

Hover over a token to see what it does.

^https?:\/\/(?:www\.)?(?:twitter|x)\.com\/(\w{1,15})(?:\/status\/(\d+))?\/?$
TokenMeaning
^Anchors the match to the start of the string
https?Matches http or https
:\/\/Literal :// scheme separator
(?:www\.)?Optional www. subdomain prefix
(?:twitter|x)\.com\/Either the legacy twitter.com or current x.com host, followed by a slash
(\w{1,15})Capture group 1: the handle, 1 to 15 word characters matching Twitter's username length limit
(?:\/status\/(\d+))?Optional /status/ segment with capture group 2 for the numeric tweet ID
\/?$Optional trailing slash, then end of string

Detailed Explanation

What it does

This pattern matches both a bare profile URL like https://x.com/handle and a link to a specific tweet like https://twitter.com/handle/status/123456789, accepting either the legacy twitter.com domain or the current x.com domain. It captures the handle and, when present, the numeric tweet ID.

Why it works

The host alternation (?:twitter|x)\.com covers the platform's rebrand while keeping backward compatibility with existing links. The handle is bounded to \w{1,15}, matching Twitter/X's documented maximum username length, which helps reject non-profile paths that happen to start with a word-like segment but are actually longer, such as internal app routes. The optional /status/(\d+) group makes the tweet ID capture opt-in, so the same pattern serves both profile and tweet URLs.

Common use cases

  • Validating a social media link field that accepts either the twitter.com or x.com domain
  • Extracting a handle and tweet ID from a pasted link to fetch tweet details via the X API
  • Normalizing links from either domain to a single canonical form during storage
  • Filtering scraped URLs to isolate links to individual tweets versus profile pages

Edge cases

  • Both twitter.com and x.com resolve successfully, reflecting the platform's 2023 rebrand
  • A trailing slash after the handle or tweet ID is accepted because of the optional \/? before the end anchor
  • Handles longer than 15 characters are rejected since \w{1,15} caps the length, matching the platform's real constraint
  • Status links without a handle are not matched since the handle group is mandatory, unlike the tweet ID which is optional
  • Reserved paths that aren't real handles, like /home or /search, would still technically match since this pattern doesn't maintain a reserved-word denylist

Limitations

  • Does not exclude Twitter/X's reserved system routes (e.g. /home, /explore, /settings) from being treated as valid handles
  • Does not validate that the numeric tweet ID corresponds to an actual existing tweet
  • Does not match other X URL types such as media galleries, lists, or spaces

Interactive Tester

Edit the pattern or text below — matching runs live in your browser.

https://twitter.com/elonmusk https://x.com/elonmusk https://twitter.com/jack/status/20

Test Cases

Editable — add your own inputs to see if they pass.

InputExpectedResult
Pass
Pass
Pass
Pass
Pass
Pass
Pass

Language Variants

Production-ready examples in 12 languages.

const twitterUrlRegex = /^https?:\/\/(?:www\.)?(?:twitter|x)\.com\/(\w{1,15})(?:\/status\/(\d+))?\/?$/;
const m = 'https://x.com/openai/status/123'.match(twitterUrlRegex);
console.log(m[1], m[2]); // 'openai' '123'

Common Mistakes

Only matching twitter.com and rejecting valid x.com links after the platform's rebrand

Fix: Use a host alternation (?:twitter|x)\.com so both domains are accepted

Allowing handles of unbounded length, which lets non-profile paths slip through as false positives

Fix: Cap the handle with \w{1,15} to match Twitter/X's actual username length limit

Treating reserved routes like /home or /settings as valid handles

Fix: Maintain a denylist of reserved words and check captured handles against it after the regex match

Performance Notes

  • The bounded handle quantifier \w{1,15} avoids unbounded backtracking compared to an open-ended + or *
  • The optional status group only adds matching cost when a /status/ segment is actually present in the input
  • Anchoring with ^ and $ avoids scanning arbitrary substrings for a match when validating a full URL string

Browser Compatibility

EngineSupportedNotes
ChromeYes
FirefoxYes
SafariYes
EdgeYes
Node.jsYes