JavaScript regex, not Perl, not an HTML parser
I debug patterns here when a String.match in the browser or in Node disagrees with what I thought I wrote. The engine is JavaScript RegExp. It is not PCRE, not Python, not Go RE2, and not the flavor inside PostgreSQL. Lookbehinds exist in modern browsers; possessive quantifiers and K do not. Recursion does not. If a pattern “works on regex101” with the flavor set to PCRE, it can still throw or silently mismatch here.
This tester always compiles with the g flag. There is no box for i, m, s, or u. If you wrap slashes around the pattern like /foo/i, the slashes become literal characters. Catastrophic backtracking can still freeze the tab: that is CPU on a nested quantifier, not tracking. Keep the sample text short while you experiment. Do not paste a 5 MB log and a greedy (.*)*.
Worked example: PAN shape, case included
Pattern [A-Z]{5}[0-9]{4}[A-Z] on ABCDE1234F matches once, positions covering the ten characters (five letters, four digits, one letter). That is the PAN layout, not a proof the PAN exists at NSDL. Same pattern on abcde1234f misses because there is no i flag. ABCDE1234F extra still matches the first ten characters under g; if you needed a whole-string check, add ^ and $: ^[A-Z]{5}[0-9]{4}[A-Z]$ will refuse the extra text. GSTIN is 15 characters with a PAN in the middle — do not reuse the PAN regex and call it GSTIN validation. Checksum tools on this site exist for a reason.
Worked example: groups on a hyphenated id
Pattern (\d{3})-(\d{2})-(\d{4}) on 123-45-6789. You should see one match, 123-45-6789, starting at index 0. The three capturing groups are 123, 45, 6789 — useful when you meant to extract, not merely detect. On 123-45 there is no match; the last group is required. A looser (\d{3})-(\d{2}) would match the prefix and leave 6789 unmatched, which is how partial KYC parsers swallow a PAN fragment and look “fine” in QA.
Worked example: the backtracking freeze
Pattern (a+)+$ on a string of twenty a characters ending in b — aaaaaaaaaaaaaaaaaaaab — is the textbook hang. The engine tries every way to split the a’s, fails the final b, and retries. I keep input under a few hundred characters when a pattern has nested + or * next to another quantifier. .* plus another .* on HTML is the same class of mistake as “parse HTML with regex”: you will match across tags you did not intend, or you will lock the tab. Email validation via a 3 KB Stack Overflow pattern belongs in the same bin; use a reasonable shape check and send a confirmation mail.
Limits of this tester
Replacements are not a first-class mode. Unicode code-point matching wants the u flag, which this UI does not pass, so some emoji and combining marks behave like UTF-16 code units. \d is ASCII digits 0–9, not Devanagari numerals. Lookbehind (?<=@)\w+ works in current Chrome/Firefox; older WebViews throw. If the pattern is invalid, you get the exception message, not a match list. Timeout is “the tab beachballs,” not a nice error.
Questions
Which flavor is this?
JavaScript RegExp with the g flag always on. Not PCRE, not Python, not RE2. regex101 must be set to JavaScript or the answer will lie.
How do I turn on case-insensitive matching?
You cannot from this UI. There is no flags field. Rewrite the character class, or test in the console with new RegExp(pattern, 'i').
Why did /foo/i not ignore case?
The slashes and the trailing i were treated as literal characters in the pattern string. Paste foo, not /foo/i.
Can a pattern freeze the tab?
Yes. Nested quantifiers such as (a+)+$ on a long non-matching string are the classic case. Shorten the sample first.
Does \d match Hindi digits?
No. \d is 0-9 unless you take the u-flag Unicode digit class in an engine that supports it. This tester does not pass u.
Is a PAN match proof the PAN is allotted?
No. The pattern only checks shape. Allotment and checksum are a different problem — use a validator, not a regex victory.