Type a pattern, paste the text you want to search, and every match lights up as you type. The panel beside your text lists each match with its groups, previews a replacement, breaks the pattern into plain English, and writes the same pattern for Python and PHP.
Paste a full literal such as /ab+c/gi and the flags split off on their own.
Matches show up here. Click a row to select the match in your text.
$1 group 1$<name> named group$& whole match$$ a dollar sign
sample / access log
The Failed requests in a log sample loads five lines from an Nginx access log and a pattern hunting for errors. Two lines match: a POST to /api/generator/jojo-stand rejected with 429, and a GET for /favicon.ico answered with 404. Here is why each piece is there.
"(?<method>GET|POST) (?<path>\S+)\S+ stops in the right spot without a lookahead.[^"]+".+" instead runs to the end of the line first, then backs up one character at a time.(?<status>[45]\d\d)[45] to [2-5] and all five lines match.The Matches tab labels each group by name, so you read method POST, path /api/generator/jojo-stand and status 429 instead of counting brackets. Click a row and the tester selects the same span in your text.
flags / g i m s u y
Most "my regex works in one place but not another" reports come down to a flag. The table lists the six toggles above the text box and the moment each one makes a visible difference.
| Flag | Effect | Where you notice the change |
|---|---|---|
| g | Keeps searching after the first match. | Turn g off and the Matches tab shows one row, and Replace swaps only the first hit. |
| i | Upper and lower case count as equal. | error finds ERROR and Error in mixed log output. |
| m | ^ and $ match at every line break, not only at the edges of the whole text. | ^\d+ against a numbered list returns every number instead of the first one. |
| s | . matches line breaks too. | <p>.*?</p> picks up paragraphs split over several lines. |
| u | Reads the pattern as Unicode code points. Turns on \p{...} and \u{1F600}, and rejects loose escapes such as \- outside a class. | ^.$ matches a single emoji only with u. Without u, an emoji counts as two units. |
| y | A match has to start exactly where the last one ended. No scanning ahead. | With y alone, the match must start at position 0. With g and y, matches have to sit back to back. |
The d and v flags are left out on purpose. d only adds index arrays, and the Matches tab already shows each start and end position. v changes character class syntax in ways older browsers reject.
port / python + php
Regex syntax looks universal until you paste a JavaScript pattern into Python and get a re.error. These are the differences we see trip people up most.
| Feature | JavaScript | Python re | PHP preg_* |
|---|---|---|---|
| Named group | (?<id>...) | (?P<id>...) | Both forms |
| Named backreference | \k<id> | (?P=id) | \k<id> or (?P=id) |
| Group in the replacement | $1, $<id> | \1, \g<id> | $1 or ${1}, no names |
| Lookbehind | Any length | Fixed width only | Fixed width per branch |
$ without m | End of the text only | End of the text, or right before a final newline | Same as Python unless you add the D modifier |
\d | 0 to 9 only | Any Unicode digit in str patterns | 0 to 9, any Unicode digit with the u modifier |
| Inline flags | No (?i). Recent browsers accept the scoped form (?i:...) | (?i) at the start | (?i) anywhere |
The Code tab does the mechanical swaps for you. Named groups become (?P<name>...) for Python, \u escapes become \x{...} for PHP, and $1 in the replacement becomes \g<1>. Behavior differences, such as lookbehind width or the meaning of $, show up as notes under the snippet instead of a silent rewrite, since rewriting them would change what the pattern matches.
timeout / 2000 ms
Some patterns take exponential time on text they fail to match. The usual shape is a quantifier inside a repeated group, such as (\w+\s?)+$ or (a|aa)+. On a 37 character line with a stray ! at the end, the engine tries every way to split the word characters between the inner and outer + before giving up. The number of ways doubles with each extra character.
In a normal page, a pattern like this freezes the tab. This tester runs every pattern in a Web Worker and shuts the worker down after 2 seconds, then reports a timeout. Press Runaway pattern under the pattern box to see the cutoff fire.
^(\w+\s?)+$^\w+(?:\s\w+)*\s?$Both patterns accept the same lines. The second one works because every repetition has to start with whitespace, so the engine has one way to split the text, not millions. Three habits keep patterns out of this trap:
[^,]*, stops at the first comma. .*, runs to the end of the line and walks back.A timeout here does not prove a pattern runs forever. A slow phone and a large paste both add time. On a short line, treat anything above a few hundred milliseconds as a warning sign for production code.
limits / read before trusting a result
a++), atomic groups ((?>...)), recursion, \A, \Z and Python's (?P<name>...) throw a syntax error here, even though PCRE accepts all of them. Use the tester to check JavaScript behavior, then read the Code tab notes before shipping to another language.(?i:...) or duplicate group names throw errors in browsers from before 2025.# in the URL. Browsers keep everything after the # away from the server, but anyone holding the link reads your text, so skip it for private data.Short answers to what developers ask us most about testing patterns.
The JavaScript (ECMAScript) engine built into your browser, the same syntax Node.js accepts. Most PCRE and Python patterns work unchanged, but possessive quantifiers, atomic groups and the Python style (?P...) named group raise a syntax error.
Four usual causes: Python wants (?P before a group name, lookbehind in Python needs a fixed width, the dollar sign in Python also matches before a final newline, and \d in Python matches digits from every script. Open the Code tab and pick Python to get a converted pattern plus notes on behavior that differs.
The pattern ran longer than 2 seconds, which almost always means catastrophic backtracking. Look for a repeated group whose contents also repeat, such as (\w+\s?)+, and rewrite the group so each repetition starts with a character the previous one cannot consume.
Write $1 for group 1, $2 for group 2 and so on. $& inserts the whole match and $$ inserts a literal dollar sign. For a named group, write a dollar sign followed by the name in angle brackets. The Reorder ISO dates sample turns 2026-03-14 into 14/03/2026 with $3/$2/$1.
They change different characters. The m flag makes the caret and dollar sign match at the start and end of each line. The s flag makes the dot match line breaks. Use m for line-by-line anchors and s for matching a block of text across lines.
No. Matching and replacing run in a Web Worker inside your browser. Copy link writes your text into the part of the URL after the # sign, which browsers do not send to servers, though anyone you share the link with sees the text.