Quick answer
This regex extracts the video ID from any common YouTube link: watch?v=, youtu.be/, /embed/, /shorts/, /live/ and youtube-nocookie.com embeds. The 11-character ID (letters, digits, hyphen and underscore) lands in the named group id, so match.groups.id gives you dQw4w9WgXcQ from https://youtu.be/dQw4w9WgXcQ?t=42. Extra parameters such as t= or list= are allowed after the ID.
- Tested examples
- Token-by-token breakdown
- Code in 5 languages
- Live tester
How to use the YouTube URL 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 YouTube URL 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 YouTube URL regex work?
Read it left to right. Each piece below matches one part of the input:
^(?:https?:\/\/)?An optional http:// or https://, so pasted links without a scheme work too.(?:www\.|m\.|music\.)?An optional www, mobile or YouTube Music subdomain.youtube\.com\/(?:watch\?(?:\S*?&)?v=|embed\/|shorts\/|live\/|v\/)youtube.com followed by one of the page types. For watch pages, other parameters may come before v=.|youtu\.be\/|youtube-nocookie\.com\/embed\/Or the short youtu.be domain, or the privacy-enhanced embed domain.(?<id>[A-Za-z0-9_-]{11})The named group id: exactly 11 base64url characters.(?:[?&#]\S*)?$Optional extra parameters (t=, list=, si=) and the end of the string. This also proves the ID was exactly 11 characters.
Which strings does the YouTube URL 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://www.youtube.com/watch?v=dQw4w9WgXcQ | Yes | The classic watch URL. |
https://youtu.be/dQw4w9WgXcQ?t=42 | Yes | Short link with a timestamp. |
https://www.youtube.com/watch?feature=share&v=dQw4w9WgXcQ | Yes | Other parameters before v=. |
https://www.youtube.com/embed/dQw4w9WgXcQ?start=30 | Yes | Embed URL from an iframe. |
https://youtube.com/shorts/dQw4w9WgXcQ | Yes | A Short. |
https://m.youtube.com/watch?v=dQw4w9WgXcQ&list=PL123 | Yes | Mobile site with a playlist parameter. |
https://www.youtube-nocookie.com/embed/dQw4w9WgXcQ | Yes | Privacy-enhanced embed. |
youtu.be/dQw4w9WgXcQ | Yes | No scheme: pasted from a share sheet. |
https://vimeo.com/123456789 | No | A different video site. |
https://www.youtube.com/watch?v=short | No | Video IDs are exactly 11 characters. |
https://www.youtube.com/watch?v=dQw4w9WgXcQextra | No | Too many characters for an ID. |
https://www.youtube.com/channel/UCuAXFkgsw1L7xaCfnd5JJOw | No | A channel page, not a video. |
https://notyoutube.com/watch?v=dQw4w9WgXcQ | No | Look-alike domains are rejected. |
How do I get the video ID in code?
Read the named group from the match:
const YT = /^(?:https?:\/\/)?(?:www\.|m\.|music\.)?(?:youtube\.com\/(?:watch\?(?:\S*?&)?v=|embed\/|shorts\/|live\/|v\/)|youtu\.be\/|youtube-nocookie\.com\/embed\/)(?<id>[A-Za-z0-9_-]{11})(?:[?&#]\S*)?$/;
const id = YT.exec(input.trim())?.groups?.id ?? null;
const embed = id ? `https://www.youtube-nocookie.com/embed/${id}` : null;Python names groups differently: the code below translates (?<id>…) to (?P<id>…) and you read it with match.group("id"). The 11-character ID format is an observed convention rather than a published guarantee, so if you need certainty, confirm the video with the YouTube Data API or the oEmbed endpoint.
Which YouTube links does this not cover?
Deliberately excluded, because none of them point at a single video:
- channel pages (
/channel/…,/@handle) and playlists without a video (/playlist?list=…), - search results and
/results?search_query=…, - attribution links and Google redirect URLs that wrap a YouTube URL in a query parameter. Decode those first with the URL decoder, then run the pattern on the inner link.
Timestamps are kept outside the ID group, so you can read them separately from the query string with new URL(link).searchParams.get("t").
How do I use the YouTube URL 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?:\/\/)?(?:www\.|m\.|music\.)?(?:youtube\.com\/(?:watch\?(?:\S*?&)?v=|embed\/|shorts\/|live\/|v\/)|youtu\.be\/|youtube-nocookie\.com\/embed\/)(?<id>[A-Za-z0-9_-]{11})(?:[?&#]\S*)?$/;
function isValid(value) {
return regex.test(value);
}
console.log(isValid("https://www.youtube.com/watch?v=dQw4w9WgXcQ"));Python
import re
pattern = re.compile(r"^(?:https?:\/\/)?(?:www\.|m\.|music\.)?(?:youtube\.com\/(?:watch\?(?:\S*?&)?v=|embed\/|shorts\/|live\/|v\/)|youtu\.be\/|youtube-nocookie\.com\/embed\/)(?P<id>[A-Za-z0-9_\-]{11})(?:[?&#]\S*)?\Z")
def is_valid(value: str) -> bool:
return pattern.search(value) is not None
print(is_valid("https://www.youtube.com/watch?v=dQw4w9WgXcQ"))- 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(`^(?:https?:\/\/)?(?:www\.|m\.|music\.)?(?:youtube\.com\/(?:watch\?(?:\S*?&)?v=|embed\/|shorts\/|live\/|v\/)|youtu\.be\/|youtube-nocookie\.com\/embed\/)(?P<id>[A-Za-z0-9_\-]{11})(?:[?&#]\S*)?$`)
fmt.Println(re.MatchString("https://www.youtube.com/watch?v=dQw4w9WgXcQ"))
}- 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?:\/\/)?(?:www\.|m\.|music\.)?(?:youtube\.com\/(?:watch\?(?:\S*?&)?v=|embed\/|shorts\/|live\/|v\/)|youtu\.be\/|youtube-nocookie\.com\/embed\/)(?<id>[A-Za-z0-9_\-]{11})(?:[?&#]\S*)?\z", RegexOptions.None, TimeSpan.FromSeconds(1));
Console.WriteLine(regex.IsMatch("https://www.youtube.com/watch?v=dQw4w9WgXcQ"));- 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?:\/\/)?(?:www\.|m\.|music\.)?(?:youtube\.com\/(?:watch\?(?:\S*?&)?v=|embed\/|shorts\/|live\/|v\/)|youtu\.be\/|youtube-nocookie\.com\/embed\/)(?<id>[A-Za-z0-9_\-]{11})(?:[?&#]\S*)?$/D';
function isValid(string $value, string $pattern): bool
{
return preg_match($pattern, $value) === 1;
}
var_dump(isValid('https://www.youtube.com/watch?v=dQw4w9WgXcQ', $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 URL Validation: http and https links with a real domain, optional port, path, query and fragment.
- Regex for Domain Names: Hostnames with valid labels, a 253-character limit and Punycode support.
- Regex for HTML Tags: Opening, closing and self-closing tags, capturing the tag name.
- 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.