Regex Tester
Write regular expressions and test them against your text in real time. Highlights matches instantly.
Updated July 11, 2026
100% Private & Secure
This tool runs in your browser.
Your data is never uploaded or stored.
How to use
- 1
Enter your regular expression.
- 2
Enter the test string.
- 3
See highlighted matches in real time.
When to use it
Building and refining a validation pattern
Iterate on patterns like emails, phone numbers, or slugs against real samples. Live match highlighting shows exactly which substrings hit, so you can tighten quantifiers or anchors before shipping the pattern into a form validator.
Extracting structured data from logs
A capture group over a log line pulls out timestamps, levels, and request IDs without writing a full parser. The tool lists every match and its groups, which is faster than eyeballing raw lines.
Porting a regex across languages
Python or PCRE patterns often use features JavaScript lacks (named groups with (?P<name>), recursion). Testing the pattern here surfaces unsupported syntax before it breaks a browser at runtime.
Debugging catastrophic backtracking
Patterns like (a+)+b on a long "aaaa..." input can hang the engine. Feeding the suspected pattern with progressively longer inputs makes the slowdown visible so you can rewrite it as an unambiguous alternative.
How it works
Literals vs new RegExp(), and why it matters
JavaScript gives you two ways to create a regexp. A literal /abc/gi is compiled once when the script loads and is immune to string-escaping bugs. The constructor new RegExp("abc", "gi") takes a string, which means you must double-escape backslashes ("\\d" for a digit) — but it is the only option when the pattern is built at runtime from user input or configuration.
Beware of the literal-as-state trap: a literal with the g or y flag carries a mutable lastIndex. Calling .test() repeatedly on the same literal alternates between true and false because the search resumes from the previous offset.
- Use a literal for fixed patterns — cleaner syntax, no escaping headaches
- Use
new RegExponly when the pattern is dynamic or config-driven - Reset
lastIndex = 0before reusing a global/sticky regexp with.test()
Flags, the u flag, and the newer v flag
Flags change how the engine interprets and searches a pattern. g finds all matches instead of stopping at the first; i ignores case; m makes ^ and $ match line boundaries; s lets . match newlines; y anchors each match at lastIndex.
The Unicode-sensitive flags are the ones most people miss. Without u, a regexp treats its input as UTF-16 code units, so emoji and astral characters like 🎉 (U+1F389) are seen as a surrogate pair — /.{1}/ matches only the first half. Adding the u flag switches to code-point semantics, so \u{1F389} and . behave correctly.
-
u— code-point semantics; required for\u{...}escapes and emoji handling -
v(Unicode sets, standardized in ECMAScript 2024) — a superset ofuthat adds set operations and properties of strings - With
v, you can intersect two Unicode properties in one class
// v flag: letters that are NOT ASCII
const re = /[\p{Letter}&&[^a-zA-Z]]/v;
re.test("é"); // true
re.test("a"); // false Backreferences, lookahead, and the ReDoS trap
A backreference like \1 matches the exact text a capture group consumed earlier — useful for matching paired quotes ((['"])(.*?)\1). Lookahead (?=...) and lookbehind (?<=...) assert what comes before or after a position without consuming it. JavaScript supports both, with variable-length lookbehind since ES2018.
The danger is catastrophic backtracking: when two quantifiers overlap, the engine tries an exponential number of ways to split the input before failing. This is the basis of regular-expression denial-of-service (ReDoS) attacks. The fix is to make patterns unambiguous — write [^,"]+ instead of .*? between delimiters, and prefer negated character classes over greedy . when you know the boundary.
Common mistakes & edge cases
A pattern works in Ruby or Python but throws "Invalid regular expression" in JS
Features like (?P<name>...) (Python), \R, or recursion are not in the ECMAScript spec. Use (?<name>...) for named groups, and test the ported pattern here first.
An emoji is matched twice, or ^.$ fails on a single emoji
You are missing the u flag. Without it, the engine sees surrogate halves. Add u (or v) so the pattern works on code points, not code units.
.test() returns true, then false, then true on the same string
A g-flagged regexp keeps lastIndex across calls. Either reset re.lastIndex = 0, remove the flag, or use String.prototype.match instead.
The browser tab freezes on long input
Catastrophic backtracking. Rewrite nested or overlapping quantifiers (e.g. (a+)+) as a single unambiguous class like a+, or use atomic grouping equivalents.