What it does
Send a pattern and a list of test inputs. Get back per-input matches with capture groups.
curl -X POST https://x402.agentutility.ai/regex-test \
-d '{"pattern":"(\\d{3})-(\\d{4})","flags":"g","inputs":["call 555-1234 or 555-5678","no numbers here"]}'
{
"pattern": "(\\d{3})-(\\d{4})",
"flags": "g",
"input_count": 2,
"matched_count": 1,
"results": [
{
"input": "call 555-1234 or 555-5678",
"matched": true,
"match_count": 2,
"matches": [
{ "match": "555-1234", "index": 5, "groups": ["555", "1234"], "named": {} },
{ "match": "555-5678", "index": 17, "groups": ["555", "5678"], "named": {} }
]
},
{
"input": "no numbers here",
"matched": false,
"match_count": 0,
"matches": []
}
]
}
$0.002 USDC. Deterministic. Pure JS RegExp under the hood. No LLM.
Why a regex tester as a paid endpoint
Two reasons.
First: agents that generate regex (via regex-from-prompt or their own LLM call) need a way to verify the output. The LLM is confident. Confidence isn't matching. An agent that runs the generated pattern through regex-test with concrete inputs catches the cases where the LLM was wrong without needing local JS execution.
Second: regex testing inside an agent's sandbox is risky. Catastrophic backtracking on a malicious input is a real DoS surface. Running the regex inside a Cloudflare Worker with strict CPU limits means a bad pattern fails fast and contained.
Named groups
If your pattern uses (?<name>...), the named object on each match maps name to the captured string. This is the difference between getting back groups: ["2024", "11", "18"] and getting back named: { year: "2024", month: "11", day: "18" }. The second one is what an agent actually wants.
Catastrophic backtrack guard
Before compiling the regex, we run a cheap heuristic check for ReDoS-shaped patterns: nested quantifiers on the same group ((a+)+), alternation between overlapping greedy branches under a quantifier ((a|aa)+). If matched, the endpoint returns 400 before ever calling new RegExp(). Not a full ReDoS analyzer — those don't exist as a one-liner — but it catches the textbook backtrack shapes.
Cloudflare Worker CPU caps catch the rest. Worst case is a 504 from us, never a worker that runs for 20s on a $0.002 call.
Limits
- Pattern: max 500 chars
- Each input: max 5000 chars
- Inputs: max 100 per request
- Matches per input: capped at 100 (with
truncated: trueflag when capped) - Standard JS regex flags only:
g i m s u y d v
Need bigger? Split the request, or ask why your test set is 5MB.
Zero-width match handling
If your pattern can match the empty string (\b, (?=...), ^), the global iteration normally infinite-loops on the same position. We advance lastIndex manually after a zero-width match so the loop terminates. Standard fix — same one V8 does internally.
What's NOT here
- No "explain this regex in English" — pair with
regex-from-promptif you want explanation - No regex-to-finite-automaton conversion
- No "fix this regex" — LLM territory, different endpoint
- No PCRE / Python / Go regex flavors. We're JS-only. Each engine has different semantics; mixing them is a bug factory.
Call it. Pairs with regex-from-prompt for the full generate-then-verify loop.