Online Regex Tester, Debugger and Explainer
Build, test and debug regular expressions with a real syntax tree, capture-group offsets, catastrophic-backtracking warnings and code export for ten languages — all inside your tab.
- Inside [ ] a dot is already literal, so escaping it is unnecessary.
Click a highlight to select that match. Hold Alt to see the raw text, F3 and Shift+F3 step through matches.
No matches
The pattern is valid, it just does not occur in this text. Check the flags — without g only the first match is reported.
[\w.%+-]+Repeat one or more times — greedy, taking as much as it can and giving back only if it must[\w.%+-]Any one character from: \w . % + -
@The character "@"[\w.-]+Repeat one or more times — greedy, taking as much as it can and giving back only if it must[\w.-]Any one character from: \w . -
\.The character ".", taken literally[A-Za-z]{2,}Repeat at least 2 times — greedy, taking as much as it can and giving back only if it must[A-Za-z]Any one character from: A–Z a–z
How it works
Write the pattern
Type it, pick one from the library, or paste a link somebody shared. The pattern is coloured by what each piece actually is, and mistakes are underlined where they happen.
Set the flags and the mode
Toggle g, i, m, s, u, v, y and d, then choose whether you are matching, replacing or splitting. Turn live mode off if you would rather nothing ran until you press the button.
Run it safely
The match happens in a Web Worker with a two-second limit. Every match comes back with its offsets and its capture groups, and the panel warns you before a pattern that could backtrack forever.
Take it with you
Copy the regex, export the matches as JSON or CSV, generate the equivalent code for ten languages, or send the result straight to another oLoveTools tool.
A parser, not a tokenizer
The pattern is parsed into a real syntax tree, so the explanation shows what contains what — and gets named groups right. A tokenizer reads (?<year>\d{4}) as a capture group followed by an optional something; a parser reads it as the named group it is.
The engine runs where it can be killed
Matching happens in a Web Worker with a watchdog. Measured here, (a+)+$ against 31 characters takes over four minutes of solid CPU on the same engine your browser uses. On the page that is a dead tab; in a worker it is a run that gets terminated after two seconds.
Matches with real offsets
The d flag is switched on behind the scenes, so every capture group carries where it starts and ends, not just what it caught. That is what paints groups inside a highlighted match and lets you jump from the list to the exact characters.
It warns you before you get burned
Nested quantifiers over overlapping characters, quantifiers around something that can match nothing, backreferences to groups that do not exist, \p{…} without the u flag, and lookbehind on a browser too old for it — all flagged before you run anything.
Export to ten languages
JavaScript, TypeScript, Python, Java, C#, PHP, Go, Rust, Ruby and grep/sed, with the flags translated properly and the replacement rewritten to each language's own syntax. Go and Rust snippets say so when the pattern uses something RE2 cannot do.
Chained to the rest of the suite
Send the replaced text, the split parts or the matches as JSON straight to WordFlow, DiffSnap, JSONFlow, CodeCard or HashBolt — without a trip through your Downloads folder.
A regex tester that cannot hang your browser
Regular expressions are the one thing a tester is expected to run before they are correct, and an incorrect one can be pathological: a pattern like (a+)+$ against a string that almost matches takes exponential time, and the browser's engine has no interrupt. RegexFlow runs every match inside a Web Worker with a two-second watchdog. If the run overruns, the worker is terminated and replaced, and you get a message instead of a frozen tab with your pattern trapped inside it.
Nothing leaves the tab
The pattern, the test text, the replacement and any file you open are processed entirely in your browser — there is no upload and no server round trip. Files are read with the browser's own FileReader. The only thing that can leave is a share link, and only when you press the button to build one.
From a working pattern to working code
Log parsing that has to survive a malformed line, validation that has to reject as well as accept, a find-and-replace across a codebase where $1 has to land in the right place, and the moment you inherit somebody else's forty-character pattern and need to know what it does before you touch it. The explanation tree, the offsets and the group table are for that moment.
Matching uses your browser's own RegExp, so what you see is exactly what your JavaScript will do — including the parts that vary, which is why the tool checks for lookbehind and unicodeSets support rather than assuming them. When you export to Python, Go or Rust, the differences are spelled out instead of quietly producing a snippet that will not compile.
Frequently Asked Questions
QIs my pattern or test text sent anywhere?
No. Everything runs in JavaScript inside your tab, including the files you open — they are read with the browser's FileReader and never uploaded. You can disconnect from the internet and the tool keeps working.
QWhat happens if I write a pattern that never finishes?
It gets killed. The match runs in a Web Worker with a two-second watchdog; if the worker does not answer in time it is terminated and a fresh one takes its place. This matters more than it sounds: measured on the same engine your browser uses, (a+)+$ against 31 characters ran for over four minutes. On the main thread that is a tab you cannot recover.
QWhich regex engine does it use?
Your browser's native RegExp, so what you test is exactly what your JavaScript will do. Where support varies the tool checks instead of assuming: lookbehind (Safari only shipped it in 16.4), the v flag for unicodeSets, and the d flag for capture-group offsets. If one is missing you are told, rather than shown a confusing error.
QWhy is the pattern explanation a tree?
Because a flat list cannot tell you what is inside what, and because a tokenizer gets things wrong that a parser does not — (?<year>\d{4}) is a named group, not a capture group followed by an optional character. Each line is linked to the exact characters it describes, so hovering one highlights them in the pattern.
QDoes the replacement support $1 and named groups?
Yes: $1 to $99, $<name>, $& for the whole match, $` and $' for the text around it, and $$ for a literal dollar. Each token you type is listed underneath with what it will become, and the generated code rewrites them into each target language's own syntax — \g<name> for Python, ${name} for Java and C#.
QCan I use it on a large file?
Yes, but past 40,000 characters the tool stops re-running on its own and waits for you to press Run — matching a large file on every keystroke is wasted work. You can also switch live mode off at any size and stay fully manual.
QWhy does the generated Go code come with a warning?
Go and Rust use RE2, which is linear-time by design and therefore has no lookahead, no lookbehind and no backreferences. If your pattern uses any of them the snippet is still shown, but with a note saying it will not compile as written — which is more useful than a snippet that silently fails.
QWhat do the coloured highlights in the test text mean?
Each match is outlined in fuchsia and the selected one is brighter. Inside the selected match, capture groups get their own violet spans, so you can see exactly which characters ended up in $1. Hold Alt to hide every highlight and read the text as it really is.