A regex engine answers one question: does this string match? RegexSolver answers questions about the patterns themselves: whether two rules overlap, whether a validator accepts more than it should, what one pattern matches that another doesn't.
10,000 req/month · full access · no payment details needed
A matcher consumes a string and a pattern and hands back a boolean. RegexSolver consumes patterns alone and reasons about the sets they describe:
Intersect two firewall rules to see exactly what they both allow. Take the difference to find strings one rule blocks and the other lets through. Shadow rules and coverage gaps surface as patterns, before they reach production.
difference(rule_a, rule_b) → gap
Prove that two validation rules are truly equivalent, or that a new rule is a strict subset of the old one. Conflicts between conditions are caught structurally instead of surfacing as silent data corruption.
subset(new_rule, old_rule) → true
Generate deterministic, valid strings from any pattern, including edge cases at exact length boundaries. Paginate through the language without duplicates — the same offset always yields the same strings.
strings(pattern, limit, offset) → ["abc01", "abc02", …]
Check that a validator is neither too strict (empty: nothing passes) nor too permissive (total: everything passes). Complement gives you the exact set of strings it rejects.
complement(validator) → rejected
| Operation | Notation | Answers | Returns |
|---|---|---|---|
| ANALYZE — inspect a pattern's language | |||
| cardinality | |A| | How many distinct strings does the pattern match? | count | ∞ |
| length | len(A) | Shortest and longest possible match. | [min, max] |
| empty / total | A = ∅ · A = Σ* | Matches nothing at all? Matches everything? | boolean |
| equivalent | A ≡ B | Same language, regardless of syntax? | boolean |
| subset | A ⊆ B | Is every match of A also a match of B? | boolean |
| pattern | re(A) | A compact, human-readable regex for any term. | regex |
| COMPUTE — derive new patterns | |||
| intersection | A ∩ B | Strings matching all of the patterns. | term |
| union | A ∪ B | Strings matching any of the patterns. | term |
| difference | A ∖ B | Strings in A but not in B. | term |
| complement | ∁A | Every string the pattern does not match. | term |
| concatenation | A · B | Patterns joined in sequence. | term |
| repeat | A{n,m} | The pattern repeated n to m times. | term |
| + strings | A → {w₁, w₂, …} | Enumerate the language itself: valid, distinct, paginated. | strings |
Every result is computed, not sampled: when RegexSolver says two patterns are equivalent, that holds for every possible string. And no input pattern, however pathological, can blow up a request.
([a-zA-Z0-9_.-])+@(([a-zA-Z-])+\.)+([a-zA-Z]{2,4})+a@b.abcdefghijacceptedthe {2,4}+ tail is not "2 to 4" — any length ≥ 2 passesuser+tag@acme.iorejectedno + in the local partOfficial SDKs for JavaScript, Python, and Java — or call the REST API directly from anything that speaks HTTP.
import { RegexSolverClient, Term } from 'regexsolver';
const client = new RegexSolverClient({
apiToken: 'REGEXSOLVER_API_TOKEN',
});
// 1. Define a complex base policy (e.g., any internal API path)
const internalApi = Term.regex("/api/v[12]/[a-z]+(/.*)?");
// 2. Define forbidden patterns (e.g., no 'admin' or 'debug' segments)
const forbidden = Term.regex(".*/(admin|debug|private)/.*");
// 3. Compute 'Set Difference': Allow the API but EXCLUDE any forbidden paths
// This is mathematically complex to write as a single regex manually!
const securePolicy = await client.difference(internalApi, forbidden);
// 4. Analyze the security of the new policy
console.log("Secure Pattern:", await client.getPattern(securePolicy));
console.log("Is it empty?", await client.isEmpty(securePolicy));
// 5. Generate 'Safe' test cases that are guaranteed NOT to hit forbidden paths
const safePaths = await client.generateStrings(securePolicy, 5, 0);
console.log("Safe Test Paths:", safePaths);
// 6. Fast client-side enforcement
console.log("Allow '/api/v1/users'?", securePolicy.matches("/api/v1/users")); // true
console.log("Allow '/api/v1/admin'?", securePolicy.matches("/api/v1/admin/")); // false10,000 req/month · full access · no payment details needed
A regex engine answers one question: does this string match? RegexSolver treats patterns as mathematical sets and answers structural questions without running any strings through them: "do these two rules overlap?", "is this validator too permissive?", or "what strings exist in A but not B?"
Think of it as static analysis for your patterns: it inspects what they can match without ever executing them on real data.
The RegexSolver engine is the open-source Rust library that implements the core set-algebra algorithms over finite automata; you can use it directly in your own Rust code.
The RegexSolver API builds on top of that engine and is exposed as a language-agnostic REST API, callable with any HTTP client, your own wrapper, or our official SDKs (JavaScript/TypeScript, Python, Java).
It also adds its own closed-source engine that converts automata back into compact, readable regex patterns, a capability the open-source library does not include.
RegexSolver supports standard character classes, quantifiers, alternation, anchors, and groups: the core constructs of pure regular languages.
Lookaheads, lookbehinds, and backreferences are not supported because they introduce context-sensitivity that makes set operations (intersection, complement, cardinality) undecidable. Keeping to pure regular languages is what makes the mathematical guarantees possible.
Yes, and this is one of RegexSolver's key strengths. Every compute operation can return a FAIR term (Fast Automaton Internal Representation), a compact binary encoding of the resulting automaton.
You can pass FAIR terms directly into subsequent API calls, skipping regex re-parsing and preserving all intermediate state with no overhead.
The core engine is written in Rust and operates on deterministic finite automata, which are immune to catastrophic backtracking (ReDoS) by construction. Every operation runs in bounded time.
For high-throughput runtime matching, the recommended pattern is to compute and cache an optimized regex with /analyze/pattern, then match it locally using your language's native engine; the SDKs include a client-side matches() method that does exactly this.
RegexSolver exposes a language-agnostic REST API, so any HTTP client works.
Official idiomatic SDKs are available for JavaScript/TypeScript (npm), Python (pip), and Java (Maven). All three are open-source and generated from the same OpenAPI spec.
The free tier covers 10,000 monthly API requests, enough for development, prototyping, and small-scale projects. Signing up requires no payment details of any kind.
See the pricing page for the full breakdown of limits.