Regex Tester
Test and debug JavaScript-compatible regular expressions in real-time with syntax highlighting and group capture tables.
Matches Detail List (2)
| # | Index | Matched Text | Capture Groups | Copy |
|---|---|---|---|---|
| 1 | 25 | [email protected] | none | |
| 2 | 74 | [email protected] | none |
Test the engine you will actually deploy
A regular expression describes a language of matching strings and a search procedure for locating them. Syntax that works in PCRE, Python, Java, .NET, RE2, or a database is not automatically valid in JavaScript. This online regex tester constructs a JavaScript RegExp from the pattern field and selected flags, so its results are directly relevant to modern browser and Node.js semantics supported by the current engine.
Enter the pattern body without literal delimiters. To test /\bcat\b/gi, put \bcat\b in Regular Expression, then turn on g and i. Typing the surrounding slashes would search for slash characters. Because the pattern comes from an input field rather than a JavaScript string literal, use one backslash for regex escapes. In source code, new RegExp("\\bcat\\b", "gi") needs doubled backslashes because the JavaScript string parser runs before the regex parser.
The page compiles as you type, reports syntax errors, highlights matched spans, and lists each match’s UTF-16 index and numbered capture groups. It includes Email Validator, URL Extractor, IPv4 Address, Date, and HTML examples. Presets are learning and extraction samples, not complete standards validators.
Build a small, adversarial test corpus
Start with one intended positive and one near miss. For an internal ticket format, try:
\b[A-Z]{2,5}-[1-9]\d*\b
Use test text such as:
Fixes OPS-42 and WEB-7; reject ops-42, A-1, OPS-0, and OPS-04.
With g, both valid candidates are shown. Without g, JavaScript stops after the first. The detail table gives each match’s index and no groups because the pattern uses none. Change the prefix to ([A-Z]{2,5})-([1-9]\d*) and the table reports group 1 and group 2. If grouping is needed only for precedence, use (?:...) to avoid unnecessary captures.
A good corpus includes minimum and maximum lengths, one character outside every allowed class, empty input, line boundaries, repeated delimiters, non-ASCII letters, malformed examples, and long hostile strings. Real production samples should be anonymized before entering any browser tool.
Understand every available flag
g global finds successive non-overlapping matches. The tester iterates with RegExp.exec() and advances manually after a zero-width result to avoid an infinite loop. It also stops after 2,000 matches as a browser-safety guard, so the count may be capped for patterns matching thousands of positions. Global does not mean “match the entire input”; anchors do that.
i case-insensitive applies JavaScript’s Unicode-aware case folding rules to supported characters, but it is not locale-specific. Turkish dotted and dotless I, for example, should not be validated through assumptions based on English casing.
m multiline changes ^ and $ so they can match around line terminators inside the input. It does not make dot match newlines. Without m, those anchors apply to input boundaries, with $ also having JavaScript end-of-input nuances around final line terminators.
s dotAll lets . include line terminators. Character classes, explicit alternatives, and negated classes retain their own behavior. .* with s can span far more than expected and amplify backtracking.
u Unicode asks JavaScript to interpret the pattern in Unicode-aware mode, including code points rather than separate surrogate halves for constructs such as dot. It also tightens escape parsing. Unicode property escapes such as \p{Letter} require u. This tool does not expose newer v, sticky y, or indices d flags.
Anchors, boundaries, and validation
Search and validation are different. /\d{4}/ finds four digits inside abc12345xyz; /^\d{4}$/ requires a four-digit input under ordinary single-line use. With m, the anchored pattern can validate one line inside a larger string, which is usually wrong for form validation. In engines or contexts where absolute boundaries differ, use the platform’s documented whole-string API rather than blindly translating anchors.
\b is a word boundary defined around JavaScript word characters, not a linguistic word detector. It behaves unexpectedly for many scripts and punctuation-heavy identifiers. \s includes more than the ASCII space. \d in JavaScript matches ASCII decimal digits, while a Unicode property escape can express broader decimal-number categories when that is intended.
Capturing groups number by opening parenthesis. Optional groups may be undefined; groups that participate but match nothing display as empty. Backreferences such as \1 require the later text to equal a prior capture. Lookahead (?=...) and negative lookahead (?!...) inspect without consuming. Modern engines also support lookbehind, but runtime support should match the oldest deployment target.
What the visualization can and cannot show
Highlights display non-overlapping consumed text. A zero-width assertion can produce a table entry with empty matched text but has no visible width to mark. Overlapping matches are not found by a normal global scan; use a lookahead such as (?=(aba)) and inspect its capture if overlap is required.
Indexes are UTF-16 code-unit offsets, matching JavaScript string APIs. An emoji can occupy two code units, so an index is not necessarily a user-perceived character count or UTF-8 byte offset. The table copies only full match text, not a selected capture group.
When a preset loads, it replaces pattern, sample, and flags. The HTML preset demonstrates backreferences for simple paired tags; regular expressions do not robustly parse arbitrary nested HTML. Use the DOM parser for untrusted or general markup. The email preset recognizes a useful subset, not every address allowed by email RFCs, internationalized domains, comments, or product policy. Similar limits apply to URL and date presets: 2026-02-31 has plausible field ranges but is not a real calendar date.
Performance and ReDoS
JavaScript’s backtracking engine can take exponential time on ambiguous patterns. A classic shape is nested repetition such as ^(a+)+$ tested against many a characters followed by !. Alternations with shared prefixes, repeated optional groups, and broad .* sections can have similar behavior. The tester’s 2,000-match cap does not protect against one catastrophic search that never reaches the loop body.
Keep quantified sections unambiguous, anchor validation patterns, bound lengths before matching, and avoid applying complex user-controlled regexes to unbounded input. Benchmark near-miss strings because successful examples often complete quickly. Consider an RE2-family engine when linear-time behavior is required, recognizing that it omits features such as backreferences and lookaround in many bindings.
Client and server validation must not rely on the client alone. Enforce limits and semantics server-side, use parsers for structured formats, and treat regex as one layer. A match does not make SQL, HTML, a filesystem path, or a URL safe for a sink; contextual escaping and authorization still apply.
Move from tester to a regression test
Copy the pattern body and flags separately. If using a regex literal, escape literal / characters as needed. If using a constructor string or JSON configuration, account for that format’s additional escaping layer. Then turn the sample corpus into table-driven tests with expected full matches and captures.
Include tests for no match, multiple global matches, Unicode input, line endings, and maximum accepted length. Pin behavior to your supported runtime versions. For replacements, add tests for $&, $1, named groups, and literal dollar signs because testing search alone does not validate replacement semantics.
Do not paste secrets, access tokens, personal records, or production logs into this page. Synthetic strings preserve structure without exposing data. A developer tool helps explain an expression; code review and automated tests preserve that explanation after edits.
Common debugging errors
- Entering
/pattern/gin the body field instead of separating pattern and flags. - Double-escaping as if the input were a JavaScript source string.
- Using
gwhen the intent was whole-input validation. - Expecting
mto make dot cross newlines instead ofs. - Treating a match index as a Unicode character or byte offset.
- Assuming captures imply overlapping matches.
- Porting unsupported PCRE syntax or flags into JavaScript.
FAQ
Why is my JavaScript regex valid in another tester but invalid here?
The other tester may use PCRE, Python, .NET, or another engine. Check flavor-specific constructs, escapes, inline flags, named-group syntax, and runtime version.
Why do I see only one match?
Enable g. Without the global flag, RegExp.exec() returns the first match only.
Can this regex tester validate email addresses perfectly?
No short expression captures all address syntax, deliverability, internationalization, and product rules. Use modest structural validation and confirm ownership by sending a verification message.
Why is an empty match not highlighted?
Zero-width matches consume no characters, so there is no span to color. The details list can still record them, subject to the safety handling.
How do I prevent regex denial of service?
Simplify ambiguous repetition, constrain input, benchmark adversarial near misses, and use a linear-time engine where the feature set permits. Treat user-supplied patterns as executable work.