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: true flag 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-prompt if 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.