Regex Tester
Free regex tester. See every match highlighted as you type, inspect capture groups, preview a replacement, and start from ready-made patterns.
Matches highlighted
Contact us at hello@toolnest.app or support@example.co.uk. Docs live at https://toolnest.app/tools/ and https://example.com/help. Server 192.168.1.42 went down on 2026-08-14 at 04:12. Brand colours are #6366f1 and #0ea5e9. Call +94 77 123 4567 or (415) 555-0132. This line has has a duplicated word.
Result
Ready-made patterns
Cheat sheet
- \d
- any digit
- \w
- letter, digit or _
- \s
- any whitespace
- .
- any character
- ^ $
- start / end
- \b
- word boundary
- *
- 0 or more
- +
- 1 or more
- ?
- 0 or 1
- {2,5}
- between 2 and 5
- (…)
- capture group
- (?:…)
- group, no capture
- (?<y>…)
- named group
- a|b
- a or b
- [a-z]
- character range
- [^a-z]
- not in range
- (?=…)
- followed by
- (?!…)
- not followed by
Regular expressions are written by trial and error, whatever anyone claims. You have a pattern, you have a body of text, and you need to see immediately which parts match, which do not, and what each capture group actually caught — before that pattern goes anywhere near production data.
This tester highlights every match live as you type, lists the groups for each one, and previews a replacement. It uses your browser's own JavaScript regex engine, so what you see here is exactly what your code will do.
How to use the Regex Tester
Write your pattern
Type between the slashes. There is no need to escape forward slashes — the delimiters are shown for readability, not parsed.
Set the flags
Global, ignore case, multiline, dot-all and unicode are toggles. Matching always runs globally so the list is complete; your own global flag decides how replace behaves.
Paste your test text
Every match is highlighted instantly and counted.
Read the group table
Each row shows where the match started, what it caught, and the contents of every numbered or named capture group.
Try a replacement
Use $1 for a numbered group or $<name> for a named one, and see the rewritten text before you commit to it.
The flags, and what they really change
| Flag | Effect | When you need it |
|---|---|---|
| g | Find every match, not just the first | Almost always, when replacing |
| i | Treat upper and lower case as equal | Matching words, emails, HTML tags |
| m | ^ and $ match at each line break, not only at the ends of the string | Working line by line |
| s | The dot also matches a newline | Matching across multiple lines |
| u | Correct handling of characters outside the basic plane | Emoji, accents, non-Latin scripts |
Without the u flag, an emoji counts as two characters and a pattern like . will match half of one, producing broken output.
Greedy, lazy, and the classic mistake
By default a quantifier is greedy: .* takes as much as it possibly can and then gives characters back only if the rest of the pattern fails. On the string <b>one</b><b>two</b>, the pattern <b>.*</b> matches the entire thing, not the first tag.
Adding a question mark makes it lazy: <b>.*?</b> stops at the first closing tag and matches just <b>one</b>. This one character is responsible for a very large share of regex bugs, and seeing the highlight jump when you add it is the fastest way to build the intuition.
Capture groups are the useful part
Matching tells you *that* something is there. Groups tell you *what* it was, which is what you almost always actually need. (\d{4})-(\d{2})-(\d{2}) matches a date and hands you the year, month and day separately.
Named groups make patterns readable and refactor-safe: (?<year>\d{4})-(?<month>\d{2}) can be referenced as $<year> in a replacement and as match.groups.year in code, so inserting a group later does not silently renumber everything.
When you need a group only for grouping — to apply a quantifier to several characters — use a non-capturing group (?:…). It keeps the numbering clean and is marginally faster.
Patterns worth being careful with
- Email addresses. The fully-correct pattern is thousands of characters long and useless in practice. Use something loose, then confirm by sending a message — that is the only real validation.
- HTML. Regex cannot parse nested structures. Extracting one attribute from known markup is fine; parsing a document is not. Use a real parser.
- Catastrophic backtracking. Nested quantifiers such as
(a+)+bcan take exponential time on a non-matching input, which is a genuine denial-of-service vector when the pattern touches user input. - Anchors. Validating input without
^and$means a pattern that matches *anywhere* in the string, which is how "valid" values sneak past a check.
Flavours are not identical
This tester uses JavaScript's engine. Most of what you write here is portable, but not all of it: lookbehind (?<=…) is unsupported in older Safari, Python uses \A and \Z rather than a multiline-sensitive ^ and $, PCRE has possessive quantifiers and atomic groups that JavaScript lacks, and POSIX tools such as grep need -E before they will accept + or ? at all.
If your pattern is destined for another language, keep it to the common subset: character classes, quantifiers, groups, alternation and anchors work everywhere.
Frequently asked questions
Which regex flavour does this use?
JavaScript, running in your own browser. That makes it exact for anything you will use in JavaScript or TypeScript, and a close guide for most other languages.
Is my test text sent anywhere?
No. Matching happens in this tab. You can safely paste logs, customer records or anything else confidential.
How do I match text across several lines?
Turn on the s flag so the dot also matches newlines, and the m flag if you want ^ and $ to apply at every line break rather than only at the start and end of the whole string.
What is the difference between .* and .*?
.* is greedy and takes as much as possible; .*? is lazy and stops at the first opportunity. On repeated HTML tags, greedy swallows all of them and lazy matches just the first.
Why does my pattern hang the page?
Nested quantifiers such as (a+)+ can backtrack exponentially on input that does not match. Simplify the pattern — this is also a real security risk if the expression ever runs on user input.
Can I use named capture groups?
Yes. Write (?<name>…) and the group appears by name in the match table; reference it as $<name> in a replacement.
100% private. Files are processed on your device and never uploaded.
Instant results. No upload queue. Processing time depends on your device.
Free forever. No signup, no watermark, no paid tier.
Works everywhere. Use a modern browser on your phone or computer.
Related tools
Regex Tester is one of all the free tools on ToolNest. No account or subscription needed — anywhere in the world.