Skip to content

PII Detector

Find personal identifiers in pasted text, with card numbers and IBANs verified against their real check digits and every detector labelled by what its check actually is.

Everything on this page runs in your browser. Nothing is uploaded, logged or sent anywhere — and unlike the other pages in this family, what you paste here is deliberately NOT written into the URL. Only the settings are. A scanner that put your secrets in a shareable link would be causing the leak it exists to prevent.

DetectorsEach one states below whether it is verified by a checksum or is only a shape.
Matched valuesMasked by default. A scanner that prints full card numbers on screen has moved the problem rather than found it.
Identifiers found
9

Every finding below says what its check actually was. A checksum-verified hit is a fact; a pattern-only hit is a shape that might be something else.

Characters scanned
421
Detectors enabled
12 of 16
Checksum-verified hits
3
Structural hits
2
Pattern-only hits
4
Rejected by a checksum
1

Findings

  1. must fixEmail address — j••••••••@e••••••••••line 3, column 10

    Basis: pattern only — local part, @, a dotted domain with a 2–24 letter final label. False positives: low — the main misses are quoted local parts and internationalised domains, both of which this rejects.

  2. must fixTelephone number — +31 •••••••••6 78line 3, column 39

    Basis: pattern only — either an E.164 number starting +, or a digit run within 28 characters of the word phone, tel, mobile, cell, gsm or telefoon. False positives: high without the label requirement — order numbers, part numbers, dates and reference codes all look like phone numbers, which is why an unlabelled national-format number is not reported here at all.

  3. must fixPayment card number · Visa — 4111•••••••••••1111line 4, column 14

    Basis: checksum-verified — Luhn check digit, length 13–19, plus an issuer-range lookup. False positives: the check digit is one of ten values, so it rejects nine in ten digit strings of the right length; the tenth still gets through.

  4. noteCard-shaped digits that fail the check — 4111•••••••••••1112line 5, column 17

    16 digits that do not satisfy the Luhn check digit, so this is not a card number. Shown because it is what the checksum is for: without it, this line would be reported as a card.

  5. must fixIBAN · NL — NL91••••••••••4300line 6, column 6

    Basis: checksum-verified — ISO 13616 country length plus the mod-97-10 check number. False positives: roughly one in ninety-seven — the tightest check on this page.

  6. must fixDutch BSN — 1112•••2333line 7, column 5

    Basis: checksum-verified — the elfproef — weights 9…2 on the first eight digits and −1 on the ninth, sum divisible by 11. False positives: about one in eleven nine-digit numbers passes by chance, so an unlabelled hit in a column of order numbers is probably noise.

  7. must fixIPv4 address — 203.••••3.42line 8, column 19

    Basis: structural rules only — four octets each in 0–255. False positives: moderate — version strings such as 10.15.7.1 and dotted numeric identifiers are indistinguishable from addresses.

  8. must fixMAC address — 00:1•••••••••A:B7line 8, column 36

    Basis: structural rules only — six colon- or hyphen-separated hex pairs. False positives: low.

  9. must fixDate of birth — 1984•••3-11line 9, column 16

    Basis: pattern only — a date within 24 characters of a birth-date label. False positives: an unlabelled date is not reported at all, because every timestamp in a log would match.

  10. must fixPassport number — NL84•••2619line 10, column 11

    Basis: pattern only — 6–10 alphanumerics within 12 characters of the word passport or paspoort. False positives: there is no reliable passport pattern — formats differ by country and none carry a public checksum — so this only fires next to a label and misses every unlabelled one.

Coverage, in both directions

Verified by a checksum: payment cards (Luhn), IBAN (mod-97-10), Dutch BSN (elfproef), UK NHS number (mod 11), Canadian SIN (Luhn), French NIR (mod 97), IMEI (Luhn). A hit from one of these is a number that satisfies a published check digit, which is a much stronger statement than a shape match.

Structure or pattern only: US Social Security numbers (no checksum exists — they have been randomly issued since 2011, so the invalid-range rules are the only check there is), email addresses, telephone numbers, IPv4 addresses, MAC addresses, dates of birth, postal codes and passport numbers.

Not detected at all: names, addresses, employers, job titles, free-text health information, national identifiers of countries not listed above, anything in a non-Latin script, and any identifier written in words rather than digits. Name and address detection needs a model or a gazetteer; a regex list of first names finds "Mark" in "mark the row as read", misses everyone not on the list, and — worst of all — makes a scan that found no names look like a scan that established there were none. In the sample text above, "Johan" and the Rotterdam depot are personal data and this tool says nothing about them.

What this assumes: the false-positive rates quoted next to each detector are arithmetic, not measurements: a check digit drawn from ten possible values rejects nine in ten random strings of the right length, and IBAN's mod-97 rejects ninety-six in ninety-seven. Those are properties of the algorithms. Nothing here has been benchmarked against a labelled corpus, and none of it is calibrated to your data. Detection is also not the same as lawfulness — a scan that comes back clean does not make a document safe to send to a processor, and the decision about what may leave your systems is not one a regex makes.

Why the checksum matters more than the pattern

Sixteen digits in a row is not a card number. Order references, tracking numbers, batch codes and concatenated timestamps are all sixteen digits in a row, and a scanner that reports them all produces a list nobody reads — which is the actual failure mode of PII scanning in practice, not missed detections. The Luhn check digit is drawn from ten values, so it rejects nine out of ten of those by construction. You can watch it happen in the sample above: two card-shaped numbers, one reported as a payment card and one as a rejected near-miss, differing in the final digit.

IBAN is stronger still — its two check digits are a mod-97 residue, so roughly ninety-six in ninety-seven candidate strings are rejected. Dutch BSN and NHS numbers use modulus 11, which leaves about one in eleven, which is why an unlabelled nine-digit number passing the elfproef is reported here as something to check rather than as a finding. That distinction is on every row for a reason: the two claims are not the same and merging them is how a scanner becomes noise.

What a clean result means

That none of the detectors you enabled matched. Given what is on the list of things not detected — every name, every address, every clinical note — a clean result is a weak signal about a document written by a human. It is a much better signal about a machine-generated payload, which is the case this is genuinely good at: a log line, an API response, a config dump, a stack trace with a request body in it.

Nothing is uploaded, and that is the point of the page

A PII detector that posted your text to a server would be an odd product. Everything here runs in the tab: no request is made, no analytics event carries the text, and unlike the other pages in this family, what you paste is deliberately kept out of the URL so that a link you share cannot carry it. Only the detector settings are in the address bar. If you need to satisfy yourself, open the network tab before you paste — there is nothing to see, which is the correct amount.

The reasoning behind this

PII Detector · Multigrid