Regex Tester
Test Regular Expressions in real-time.
About the Regex Tester (JavaScript flavour)
A regular expression is a compact pattern language for matching text. It drives search and replace in editors, input validation in forms, log filtering, route matching in web frameworks and tokenising in compilers. It is also easy to get subtly wrong, which is why a live tester is worth keeping open while you write one.
This page compiles your pattern with the browser's native RegExp engine, runs it against the test string as you type, highlights every match and counts them. Invalid patterns show the engine's own error message instead of failing silently. Patterns that can match an empty string are handled without freezing the page. Everything runs locally, so you can paste production log lines or customer records without them leaving your machine.
Flags you can type in the small box
| Flag | Meaning |
|---|---|
g | Global: find every match. Without it, only the first match is highlighted. This is the default here. |
i | Case-insensitive. |
m | Multiline: ^ and $ match at the start and end of each line, not just the whole input. |
s | dotAll: . also matches newline characters. |
u | Unicode: enables \p{...} property escapes and treats emoji and other astral characters as one character. |
y | Sticky: the match must start exactly at the current position. Mostly used by tokenisers. |
d | Generate start and end indices for capture groups (ES2022). |
v | Unicode sets (ES2024): set operations inside character classes, such as [\p{L}--[a-z]]. Needs a recent browser. |
A repeated or unknown letter produces the error "Invalid flags", which is shown above the test string.
Type the pattern, not the string literal
The pattern box takes raw regex syntax, the same text you would put between the slashes of a literal. Write \d+, not \\d+. Doubling the backslashes is only necessary when the pattern lives inside a JavaScript string passed to new RegExp("\\d+"). Characters with special meaning that need a backslash to be matched literally are . * + ? ^ $ ( ) [ ] { } | \. A forward slash does not need escaping here because the tool uses the constructor rather than a literal.
Greedy quantifiers, anchors and the dollar sign
*, + and {n,m} are greedy: they grab as much as possible and give back only what the rest of the pattern needs. Append ? to make them lazy, so <.+?> matches one tag where <.+> would swallow a whole line. Anchors are cheap and prevent partial matches: a validator should be ^[6-9][0-9]{9}$, not [6-9][0-9]{9}, which also matches inside a longer number. One JavaScript-specific detail: without the m flag, $ matches only at the very end of the input, whereas in Python and PCRE it also matches before a final newline.
Groups, lookarounds and backreferences
(...)captures;(?:...)groups without capturing, which is faster and keeps numbering tidy.(?<year>\d{4})is a named group. Refer to it later in the pattern with\k<year>and in a replacement string with$<year>. Numbered groups use\1and$1.(?=...)and(?!...)are lookahead;(?<=...)and(?<!...)are lookbehind. All four are supported in current browsers, and JavaScript lookbehind may be variable length, which Python's re module does not allow.- In code,
str.match(re)returns the first match with its groups;str.matchAll(re)needs thegflag and yields every match;str.replace(re, fn)can compute each replacement.
Unicode, digits and Indian scripts
In JavaScript \d always means [0-9] and \w means ASCII letters, digits and underscore, even with the u flag. Python 3 is different: its \d matches digits in any script. To match Devanagari text use a property escape, /\p{Script=Devanagari}+/u, and /\p{L}+/u for letters of any script. Without the u flag a single emoji is two UTF-16 code units, so /^.$/ fails on it while /^.$/u matches. Word boundaries (\b) are ASCII-only as well, which trips up validators for names in Hindi, Tamil or Telugu.
Validation patterns for common Indian identifiers
These check the format only; they cannot confirm that a number is real or belongs to someone.
| Value | Pattern | Notes |
|---|---|---|
| PIN code | ^[1-9][0-9]{5}$ | Six digits, first digit never zero. |
| Mobile number | ^(\+91[\s-]?)?[6-9][0-9]{9}$ | Ten digits starting with 6 to 9, optional +91 prefix. |
| PAN | ^[A-Z]{5}[0-9]{4}[A-Z]$ | Five letters, four digits, one letter. Add the i flag if you accept lowercase. |
| IFSC | ^[A-Z]{4}0[A-Z0-9]{6}$ | Four-letter bank code, a zero, six alphanumerics. |
| GSTIN | ^[0-9]{2}[A-Z]{5}[0-9]{4}[A-Z][1-9A-Z]Z[0-9A-Z]$ | Two-digit state code, the PAN, an entity code, the letter Z, a check character. |
| Aadhaar | ^[2-9][0-9]{11}$ | Twelve digits not starting with 0 or 1. The real check digit uses the Verhoeff algorithm, which regex cannot compute. |
Catastrophic backtracking (ReDoS)
Browser engines match by backtracking. A pattern with nested quantifiers such as ^(a+)+$ or ^(\w+\s?)*$ tries an exponential number of ways to split the input when a match fails, so a string of thirty letters followed by a stray character can take seconds and a longer one can hang the tab. On a server the same pattern is a denial-of-service hole. Avoid quantifiers nested inside quantifiers, anchor the pattern, make adjacent parts mutually exclusive (for example [a-z]+@[a-z]+ rather than .+@.+), and cap the input length before matching. If untrusted users supply the pattern itself, use a linear-time engine such as RE2 or Go's regexp package.
Do not parse HTML or JSON with regex
Both formats nest, and regular expressions cannot count nesting depth. A pattern that works on today's markup breaks on the first attribute containing an angle bracket or an escaped quote inside a string. Use a DOM parser for HTML andJSON.parse or the JSON formatter for JSON; regex is fine for pulling one field out of a log line.Portability to other engines
| Feature | JavaScript | PCRE (PHP, grep -P) | Python re |
|---|---|---|---|
| Named group syntax | (?<n>...) | (?<n>...) or (?P<n>...) | (?P<n>...) |
Possessive a++, atomic (?>...) | No | Yes | Yes since 3.11 |
Anchors \A \Z | No (use ^ $ without m) | Yes | Yes |
\d matches non-ASCII digits | No | Only in UTF mode with UCP | Yes for str patterns |
| Variable-length lookbehind | Yes | Limited | No |
grep -E '^[6-9][0-9]{9}$' numbers.txt # POSIX extended syntax
grep -P '(?<=id=)\d+' app.log # PCRE, needed for lookbehind
rg -o '\b[A-Z]{5}[0-9]{4}[A-Z]\b' *.csv # ripgrep, Rust regex crate
node -e "console.log('a1b22'.match(/\d+/g))"
python3 -c "import re; print(re.findall(r'\d+', 'a1b22'))"How to use
- Type the pattern between the two slashes, without slashes of your own and without doubling backslashes.
- Edit the flags box if needed. It starts as g so every match is highlighted; remove g to see only the first match.
- Paste the text to test into the Test String box. Matches are highlighted below and counted on the right.
- If the pattern is invalid, the engine error (for example Unterminated group or Invalid flags) appears under the pattern box.
- Copy the finished pattern into your code as a literal, or double the backslashes if it goes into a string passed to new RegExp.
Common use cases
- Validating form fields such as PIN codes, mobile numbers, PAN, IFSC and GSTIN before submission.
- Extracting timestamps, status codes or request IDs from server log lines for a monitoring rule.
- Prototyping a search-and-replace with capture groups before running it across a codebase.
- Checking a route or path pattern against a list of sample URLs.
- Testing whether a pattern from a Python or PHP project behaves the same in JavaScript.
- Reproducing a slow pattern on a short string to confirm catastrophic backtracking before it reaches production.
Frequently asked questions
Which regex flavour does this tester use?
Why is my pattern matching too much?
Why is only one match highlighted?
What does Invalid flags mean?
Does it support lookbehind and named groups?
How do I match Hindi or other non-Latin text?
Why does the page freeze on a long test string?
Can I preview a replacement here?
Related developer tools
Advertisement