Regex Tester
Test JavaScript regular expressions in your browser in real time. Highlights matches, shows capture groups, supports all flags.
Highlighted result
Match details
Common patterns
📖 Where people get stuck
Evaluates a pattern live with the JavaScript regular expression engine, highlighting the matches and listing the capture groups. Everything runs in the browser. The dialect here is JavaScript — a pattern that works here will not necessarily work unchanged in PHP, Python or Go, because the meaning of character classes, the availability of lookbehind and the handling of Unicode all differ by language.
| Case | What happens | What to do |
|---|---|---|
| With the g flag, the second call gives a different answer | A regular expression object with the g flag carries state in lastIndex. Call test() repeatedly on the same object and it resumes from the previous match position, so the same string alternates between true and false. This turns fatal when the regular expression is defined at module top level and reused: the state survives across requests, producing a validation that occasionally passes when it should not, and never reproduces. A test that calls it once will not catch it. |
Do not put g on a regular expression you use with test() or exec(). People add it meaning to match everything, but test() asks whether there is at least one, so g is unnecessary. To collect every match, use str.matchAll(re), which does require g. If a shared object genuinely needs g, set re.lastIndex = 0 immediately before each use. And the cost of writing the literal inside the function every time is negligible — engines cache regular expression literals, so avoiding the shared object is safer and costs essentially nothing. |
| Japanese and emoji do not match the way you expect | \w means ASCII letters, digits and underscore only — it never matches Japanese. \b, the word boundary, fails for the same reason inside Japanese text. More serious still are surrogate pairs: without the u flag, emoji and certain rarer CJK characters count as two, so . matches half of one and a class such as [𠮷] becomes a nonsensical set meaning either of these two surrogates. Almost every case of characters being mangled by a length count or a truncation traces back to this. |
Always add the u flag. That alone makes surrogate pairs count as one character and additionally unlocks the \p{...} Unicode property escapes. For Japanese that means \p{Script=Hiragana}, \p{Script=Katakana} and \p{Script=Han} — more accurate than a range such as [ぁ-んァ-ヶ一-龠], and the intent is readable. For emoji, \p{Extended_Pictographic}, though skin tones and family emoji are sequences of several code points, so treating one as a single character needs Intl.Segmenter — regular expressions can only take you so far. If your goal is counting characters, use Intl.Segmenter rather than a regular expression. |
| A greedy match swallows far more than intended | .* matches as much as it possibly can. So applying <.*> to <div>A</div><div>B</div> produces a single match running from the first < to the last >. Since . does not match a newline by default it stops at line ends, but add the s flag and it swallows the whole file. The behaviour is correct; the problem is that when it diverges from your expectation it shows up as passing in tests and breaking on the longer inputs in production. |
Use the lazy .*?, or better, write it as a negated class such as [^>]* — the latter never backtracks, so it is faster and states the intent plainly. The more fundamental advice, though, is do not parse HTML with a regular expression: a > inside an attribute value, comments, CDATA and nested tags of the same name will break it. Use DOMParser in a browser and a real HTML parser on the server. Regular expressions suit line-oriented, unstructured text in a known format — a log line, a line of a configuration file, validating the shape of an identifier. Anything with nesting is outside their remit. |
Nested quantifiers are where ReDoS lives. An expression with a repetition inside a repetition, such as (a+)+$ or (\w+\s?)*$, takes exponential time on input that does not match — thirty characters is enough to hold a server CPU at 100 percent for minutes. Ironically, the place this turns up most often is the strict email validation regular expression, and it has caused outages at large services more than once. There are three defences: do not write nested quantifiers, cap the length of the input, and use an engine that does not backtrack — the Go standard regexp, the Rust regex crate, or RE2. Keep the dialect differences in mind too: JavaScript has no \A or \z, and you substitute ^ and $ without the m flag. Lookbehind arrived in ES2018, but Safari only supported it from 16.4, so avoid it if you must support older environments.
📖 How to Use
-
1
Enter your patternType your regex (e.g. \\d{3}-\\d{4}). Toggle flags (g / i / m / s) as needed.
-
2
Paste test textPaste target text and matches are highlighted in real time.
-
3
Inspect capture groupsRight panel shows position and capture group values for each match, plus replace preview.
❓ Frequently Asked Questions
Which regex engine is used?
Can I match Japanese character classes?
How fast is it?
Can I convert to regex in other languages?
🐛 Found a bug or issue with this tool?
Free to use, no signup. Even just the steps to reproduce are helpful. Reports go directly to the operator and help us fix issues.
Thanks for your report!
Your report has been delivered to the operator and will be used to improve the tool.