piidetectionapi.com
Home
Solutions - Fundamentals
What Is PII Detection? NER vs Regex vs Rules Accuracy, Precision & Recall PII in Test Data
Solutions - Compliance
GDPR Personal Data HIPAA PHI Detection CCPA / CPRA PCI DSS Card Data
Solutions - AI & LLM Safety
LLM Guardrails Chatbot PII Filtering RAG Pipelines
Solutions - Data Discovery & DLP
Data Loss Prevention Log File Scanning Support Tickets Email Scanning Documents & PDFs Database Discovery ETL & Streaming Pipelines
Industries - Financial
Banking Fintech Insurance
Industries - Healthcare
Healthcare Pharma & Clinical Trials Telehealth
Industries - Public Sector & Legal
Government & FOIA Law Enforcement Law Firms & eDiscovery Education (FERPA)
Industries - Technology
SaaS Platforms Cybersecurity & IR Telecommunications Gaming & Platforms
Industries - Other
HR & Recruiting Retail & E-commerce Call Centers & BPO Real Estate Travel & Hospitality Marketing & AdTech
How-to Guides - Identity & Contact
Detect Names Detect Email Addresses Detect Phone Numbers Detect Physical Addresses Detect Dates of Birth
How-to Guides - IDs & Financial
Detect SSNs Detect Passport Numbers Detect Drivers Licenses Detect Credit Card Numbers Detect Bank Accounts & IBAN
How-to Guides - Technical & Health
Detect IP & Device IDs Detect Medical Records & PHI
Resources
Pricing API Docs Supported Entities Languages About Contact Sign In Try the Live Demo Get Started
How-To Guide

How to Detect Driver's License Numbers

Every US state issues driver's license numbers in a different format, and international licenses add dozens more. Learn how PII Detection API finds, classifies, and locates license numbers in claims, tickets, HR files, and transcripts — with offsets, confidence scores, and optional masking.

12 min read
cURL, Python & JavaScript examples
Updated Aug 2026

Overview

The driver's license is the identity document Americans actually carry. It gets photographed at car rental counters, typed into insurance claim forms, read aloud to call center agents, photocopied by HR departments, and pasted into support tickets whenever someone needs to prove who they are. As a result, driver's license numbers leak into unstructured text at a rate that surprises most compliance teams the first time they run a scan: claim narratives, onboarding emails, background-check correspondence, chat transcripts, even calendar invites ("bring DL# D1234567 to the appointment").

Detecting these numbers automatically is harder than it sounds, because there is no such thing as the driver's license number format. Each of the 50 US states — plus DC and the territories — defines its own scheme, ranging from plain 8-digit numbers to 14-character codes that algorithmically encode the holder's surname and birth date. International licenses multiply the variety further. PII Detection API addresses this with the DRIVERS_LICENSE_NUMBER entity type: a context-aware detector that recognizes the full catalog of state and national patterns and, crucially, uses the surrounding language to decide whether a matching string really is a license number rather than a policy number, VIN, or employee ID.

For every hit, the API returns the entity type, the exact matched text, its start and end character offsets, and a confidence score — and can optionally rewrite the text with the value masked. That structure is what lets you build precise redaction, alerting, or quarantine logic instead of blunt keyword filters.

Input Text
Claimant Maria Torres (CA license D1234567, DOB 04/12/1985) rear-ended at the intersection; police report attached.
Detected & Masked Output
Claimant [PERSON_NAME] (CA license [DRIVERS_LICENSE_NUMBER], DOB [DATE_OF_BIRTH]) rear-ended at the intersection; police report attached.
All 50 States
Every state scheme recognized, plus DC, territories, and CDLs
Context-Aware
Separates license numbers from VINs, policy numbers, and IDs
International
UK, Canadian, EU, Australian, and Indian license formats

You can watch the detector work on your own sample text in the interactive demo before writing any code; the sections below cover the risk profile, the formats, and complete integration examples against the detection API.

Why License Numbers Are Sensitive

A driver's license number is a government-issued identifier tied to a verified legal identity, a photograph, a home address, and a date of birth. That combination makes it one of the most useful single artifacts for impersonation.

Identity theft and synthetic identity fraud

License numbers are a staple of full-identity "fullz" packages traded after breaches, and they play a specific role in synthetic identity fraud: a real license number lends credibility to an otherwise fabricated identity when fraudsters open accounts, pass knowledge-based verification, or file fraudulent unemployment and insurance claims. Because a license number changes only when a person moves states or the state redesigns its scheme, a leaked number stays exploitable for years — much like the bank account identifiers covered in our financial account detection guide.

The Driver's Privacy Protection Act

The DPPA (18 U.S.C. §2721) is one of the few US federal privacy statutes aimed at a single record type: it prohibits state DMVs — and anyone who obtains data from them — from disclosing personal information from motor vehicle records outside a list of permissible uses. Insurers, employers running motor vehicle record checks, tow companies, and data resellers all inherit DPPA obligations when DMV-sourced data flows into their systems. Once that data lands in free-text fields, proving you control it requires finding it first, which is precisely the discovery problem automated detection solves.

Breach notification and CCPA/CPRA

Nearly every US state's breach-notification statute enumerates "driver's license number or state identification card number" as a data element whose exposure, in combination with a name, triggers mandatory notification. California's CCPA/CPRA goes further, both defining license numbers as personal information subject to consumer rights and creating a private right of action when they are breached due to unreasonable security. In practical terms: a support database that silently accumulates license numbers in ticket bodies is a latent notification event. The CCPA/CPRA compliance guide covers how detection supports rights-request fulfillment and breach-scope analysis.

Rule of thumb: if a text store contains names, assume it also contains license numbers wherever your business touches vehicles, claims, employment screening, or age verification. Scan before an incident forces you to.

The Format Chaos Problem

Social Security numbers have one format. Credit cards have a checksum. Driver's licenses have neither luxury: the number is whatever each issuing jurisdiction decided, often decades ago, sometimes with logic that actively resembles other data.

Consider what a detector must accept as potentially valid: 12345678 (Texas or Pennsylvania), D1234567 (California), T520-4839-2210-01 (a hyphenated Illinois-style rendering), WDLABCD456DG (Washington's legacy name-derived format), and 999123456 (New York's plain nine digits — which is also the shape of an SSN and an ABA routing number). Some states encode personal data directly into the number: Florida and Illinois derive leading characters from a Soundex encoding of the surname plus coded birth-date digits, and Washington's older format embedded chunks of the holder's name. That means two things: first, the number itself can leak name and birth-date information; second, the character mix varies so widely that no single expression can describe "a license number".

The practical consequence is that license detection is a classification problem, not a pattern-matching problem. The engine treats format plausibility as one signal among several — label vocabulary ("DL#", "lic. no.", "driver's license", "CDL"), state references ("CA license", "issued by Ohio BMV"), document genre (claim form vs. purchase order), and co-occurring entities like names, addresses, and dates of birth — and only then commits to the DRIVERS_LICENSE_NUMBER label with a confidence score you can threshold against. The complete list of identity-document entities is on the entities page.

Quick Start

Detection is a single POST request. Send the text plus the entity types you care about; for license-bearing documents the natural companions are PERSON_NAME and DATE_OF_BIRTH, since the three travel together on every license and claim form.

curl -X POST https://piidetectionapi.com/api/moderate.php \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "YOUR_API_KEY",
    "api_type": "pii_detection",
    "text": "Driver James Okafor, TX DL 38291045, DOB 09/23/1990, cleared the MVR check.",
    "entities": ["DRIVERS_LICENSE_NUMBER", "PERSON_NAME", "DATE_OF_BIRTH"],
    "mask_mode": "replace"
  }'
import requests

resp = requests.post(
    "https://piidetectionapi.com/api/moderate.php",
    json={
        "api_key": "YOUR_API_KEY",
        "api_type": "pii_detection",
        "text": "Driver James Okafor, TX DL 38291045, DOB 09/23/1990, "
                "cleared the MVR check.",
        "entities": ["DRIVERS_LICENSE_NUMBER", "PERSON_NAME",
                     "DATE_OF_BIRTH"],
        "mask_mode": "replace",
    },
    timeout=30,
)
data = resp.json()
for e in data["detected_entities"]:
    print(e["type"], e["text"], e["start"], e["end"], e["confidence"])
const resp = await fetch("https://piidetectionapi.com/api/moderate.php", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    api_key: "YOUR_API_KEY",
    api_type: "pii_detection",
    text: "Driver James Okafor, TX DL 38291045, DOB 09/23/1990, " +
          "cleared the MVR check.",
    entities: ["DRIVERS_LICENSE_NUMBER", "PERSON_NAME",
               "DATE_OF_BIRTH"],
    mask_mode: "replace"
  })
});
const data = await resp.json();
data.detected_entities.forEach(e =>
  console.log(e.type, e.text, e.start, e.end, e.confidence));

The response carries the structured entity list plus the masked text:

{
  "detected_entities": [
    {"type": "PERSON_NAME", "text": "James Okafor", "start": 7, "end": 19, "confidence": 0.97},
    {"type": "DRIVERS_LICENSE_NUMBER", "text": "38291045", "start": 27, "end": 35, "confidence": 0.94},
    {"type": "DATE_OF_BIRTH", "text": "09/23/1990", "start": 41, "end": 51, "confidence": 0.96}
  ],
  "anonymized_text": "Driver [PERSON_NAME], TX DL [DRIVERS_LICENSE_NUMBER], DOB [DATE_OF_BIRTH], cleared the MVR check.",
  "entities_detected": 3,
  "processing_time_ms": 156,
  "mask_mode_used": "replace",
  "status": 200
}

Note that the bare 8-digit number was classified as a license because of "TX DL" and the surrounding driver-record context; the same digits in an invoice would have been left alone. If you only need discovery — flagging documents for review without altering them — omit mask_mode and read just detected_entities. Full parameter semantics live in the API documentation.

US State Formats

The table below samples the diversity a detector must handle. It is not exhaustive — several states have issued multiple schemes over the years, and old numbers remain valid identifiers in historical records — but it shows why "match a license number" cannot be a single expression.

State Format Example Notes
California1 letter + 7 digitsD1234567Letter is sequential, not personal
Texas8 digits38291045Collides with order and invoice numbers
Florida1 letter + 12 digitsT520483922100Leading letter + digits Soundex-encode the surname and birth date
Illinois1 letter + 11 digitsT52048392210Encodes name and DOB; often written with hyphens
New York9 digits999123456Same shape as SSN and ABA routing numbers
New Jersey1 letter + 14 digitsO123456789012345Longest common US format; encodes name/DOB elements
Washington12 alphanumericWDLABCD456DGLegacy format derived from holder's name; newer licenses use WDL + 9 alphanumeric
Wisconsin1 letter + 13 digitsT5204839221001Soundex-based like Illinois/Florida
Michigan1 letter + 12 digitsT520483922100Same shape as Florida — state context disambiguates
Ohio2 letters + 6 digitsTL545796Compact format; BMV correspondence is a common source
Pennsylvania8 digits99123456Identical shape to Texas
Virginia1 letter + 8 digitsT12345678Also accepts SSN-derived legacy numbers in old records
Maryland1 letter + 12 digitsT520483922100First letter matches surname initial
Georgia9 digits053815396Another nine-digit collision case

Two structural facts stand out. First, at least five populous states use plain 8- or 9-digit numbers, indistinguishable by shape from SSNs, routing numbers, ZIP+4 codes, and internal record IDs — classification must come from context. Second, the Soundex-encoding states (Florida, Illinois, Wisconsin, Maryland, Michigan share the family) mean a license number can itself be a partial disclosure of name and birth date, which is worth remembering when you decide whether last-four-style partial masking is acceptable for your use case.

Why Regex Alone Fails

It is tempting to concatenate fifty state patterns into one giant alternation and call it a detector. Teams who try this discover three failure modes within the first week.

  • Cross-state collisions: the union of all state patterns is so broad that it matches most alphanumeric tokens between 8 and 15 characters. A Michigan-shaped string is also a Florida-shaped string and a Maryland-shaped string; a matcher cannot even attribute a state, let alone reject non-licenses.
  • Collisions with other identifier families: VINs (17 alphanumeric, but substrings match), insurance policy numbers, claim numbers, employee IDs, vehicle plate numbers, and case references all live in exactly the documents where license numbers appear. An insurance claim narrative is a minefield of license-shaped tokens that are not licenses.
  • No checksum to rescue precision: unlike IBANs or credit cards, US license numbers carry no verifiable check digit (a few states have internal checks, but they are unpublished or inconsistent). There is no arithmetic backstop; precision has to come from language understanding.

This is the textbook case for transformer-based NER over rules: the model reads "policy HX-4483920 covers driver, MI license T520483922100" and labels only the second token, because it has seen millions of claim-like sentences and learned what role each token plays. The NER vs regex comparison guide quantifies the precision gap on identifier-heavy text if you want the benchmark detail.

Anti-pattern: running a broad license regex first and "confirming" hits with the API doubles your cost and halves your precision — the regex pre-filter discards the context the model needs. Send the raw text; let the model see the whole sentence.

International Licenses

Global operations — ride-share platforms, rental fleets, multinational HR — meet license formats from every jurisdiction their drivers hold. A few of the most common:

Country Format Example Notes
United Kingdom16 charactersTORRE704129MJ9ABEncodes first 5 letters of surname, DOB digits, initials — the number itself leaks identity data
CanadaPer provinceT1234-56789-01234 (ON)Ontario 15 alphanumeric encoding name/DOB; Quebec 13; BC 7 digits
Germany11 alphanumericB072RRE2I55Issuing-authority prefix + serial + check character
AustraliaState-based, 6–10 alphanumeric12345678 (NSW)Victoria up to 10 digits; some states now issue letters+digits
India15 charactersMH12 20240012345State code + RTO code + issue year + serial (SS-RR-YYYYNNNNNNN)

The UK format deserves special mention: because it embeds the surname fragment and coded date of birth, a leaked UK license number is effectively a leaked name-plus-DOB pair under GDPR analysis — treat it with the same severity as the underlying attributes. Detection works across 60+ languages, so a German claim narrative or Hindi onboarding form is parsed with native context rather than translation; see the supported languages page for coverage.

Where License Numbers Appear

Knowing where license numbers concentrate tells you where to point your first scans.

Auto insurance

The densest source by far. First notice of loss (FNOL) narratives, adjuster notes, quote requests, and subrogation correspondence routinely contain the license numbers of every driver involved in an incident — policyholder and third parties alike, meaning you hold license data for people who are not even your customers. The insurance industry guide walks through claim-pipeline integration patterns.

HR, fleet, and gig platforms

Employment verification, commercial fleet onboarding, and ride-share/delivery driver applications all collect license numbers, and they leak from structured fields into recruiter emails, background-check follow-ups, and applicant-tracking notes. CDL numbers in trucking and logistics carry the same risk with an additional federal overlay. See the HR & recruiting guide for the employment-context view.

DMV correspondence, rentals, and incident reports

DMV letters quoted into CRM tickets inherit DPPA obligations. Car rental agreements and damage disputes capture licenses at the counter. Traffic incident and police reports pasted into legal or claims files bring license numbers of drivers, witnesses, and owners. Age-verification flows (car sharing, alcohol delivery) add a steady drip through customer support channels.

Across all of these, the pattern is identical: a structured system collected the number legitimately, and free text carried it somewhere ungoverned. Detection at the ingestion boundary of each free-text store is the fix.

More Code Examples

Insurance claim scan with full identity context

Claims text mixes license numbers with names, addresses, and birth dates; scanning them together produces a complete redaction in one call:

import requests

claim_text = open("fnol_narrative.txt").read()[:50000]

resp = requests.post(
    "https://piidetectionapi.com/api/moderate.php",
    json={
        "api_key": "YOUR_API_KEY",
        "api_type": "pii_detection",
        "text": claim_text,
        "entities": ["DRIVERS_LICENSE_NUMBER", "PERSON_NAME",
                     "ADDRESS", "DATE_OF_BIRTH", "NATIONAL_ID"],
        "mask_mode": "replace",
        "threshold": 0.5,
    },
    timeout=30,
)
data = resp.json()
print(data["anonymized_text"])
print(f"{data['entities_detected']} identifiers masked "
      f"in {data['processing_time_ms']}ms")

Hash mode for claims analytics

Fraud analytics needs to link the same driver across claims without storing the license number itself. mask_mode: "hash" substitutes a consistent token per unique value, so joins and repeat-claimant detection keep working on sanitized data:

// Sanitize claim notes before loading into the analytics warehouse
async function sanitizeClaim(note) {
  const resp = await fetch("https://piidetectionapi.com/api/moderate.php", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      api_key: process.env.PII_API_KEY,
      api_type: "pii_detection",
      text: note,
      entities: ["DRIVERS_LICENSE_NUMBER", "PERSON_NAME"],
      mask_mode: "hash"  // same license => same token across claims
    })
  });
  const data = await resp.json();
  return data.anonymized_text;
}

Excluding policy numbers with custom_instruction

If your policy numbers happen to look license-shaped (a common complaint in insurance), tell the API in plain English instead of fighting thresholds:

curl -X POST https://piidetectionapi.com/api/moderate.php \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "YOUR_API_KEY",
    "api_type": "pii_detection",
    "text": "Policy A98213345 renewed. Insured driver holds FL license T520483922100.",
    "entities": ["DRIVERS_LICENSE_NUMBER"],
    "mask_mode": "replace",
    "custom_instruction": "Our policy numbers start with a letter followed by 8 digits and are labeled Policy; never classify them as driver license numbers."
  }'

Only the Florida license is masked; the policy number survives intact. For audit sweeps of historical archives, pair this with a lowered threshold (0.35–0.4) and human review of mid-confidence hits, exactly as you would for account numbers; for inline masking of agent-visible text, keep the threshold at 0.6 or higher so legitimate reference numbers are not mangled.

Best Practices

1. Scan for the identity cluster, not the number alone

Breach statutes trigger on name plus license number. Detecting DRIVERS_LICENSE_NUMBER together with PERSON_NAME, ADDRESS, and DATE_OF_BIRTH lets you score documents by combination risk — a bare license-shaped token is low priority; the full cluster is an incident-in-waiting.

2. Give the model state context when you have it

If your pipeline knows the record's jurisdiction (a state field on the claim, the DMV the letter came from), keep that metadata adjacent to the text you send. Phrases like "TX DL" or "Ontario licence" measurably sharpen classification of the format-ambiguous states.

3. Mask on offsets, not string search

Always cut using the returned start/end positions. License numbers recur in documents with different framing, and a digit string may be a substring of a longer identifier; find-and-replace will eventually corrupt something a regulator later asks about.

4. Treat encoded formats as compound PII

UK, Florida, Illinois, and similar numbers embed surname and birth-date material. When you report breach scope or answer a CCPA deletion request, count these as carrying those attributes, not just an opaque ID.

5. Catch them at ingestion

A sub-200ms synchronous check on the ticket webhook, claim-intake API, or transcript pipeline keeps license numbers out of the store permanently; retroactive lake scans are for the backlog, not the steady state. Median processing time comfortably fits inline budgets — verify against your own payloads via the demo or a free key from the get started page, with volume tiers on the pricing page.

Edge Cases

Punctuation and casing variants

People transcribe licenses with hyphens (T520-4839-2210), spaces, dots, or in lowercase; Illinois numbers in particular are conventionally hyphenated. The detector normalizes separators before format assessment while returning offsets against the original text, so masking stays exact.

OCR from license photos

Uploaded license images run through OCR arrive with classic confusions — O/0, I/1, B/8 — and jumbled field order (the number adjacent to height, class, and expiry fields). The model tolerates common substitutions inside otherwise coherent license contexts and uses the card's field vocabulary ("DL", "CLASS", "EXP", "DOB") as strong evidence. For full document workflows, the document scanning guide covers the OCR pipeline end to end.

Labels: DL#, CDL, MVR, and friends

Abbreviated labels ("DL#", "CDL:", "lic no", "OLN" on police reports) are learned vocabulary, not hardcoded triggers — they raise confidence but their absence does not prevent detection when the discourse context is strong, as in a DMV letter.

License plates are not licenses

Plate numbers ("7ABC123") appear in the same incident reports and are frequently confused by naive matchers. The model separates them: plates attach to vehicles and phrases like "plate", "tag", "registration", while license numbers attach to persons. If you need both flagged, add plate-bearing text to your review flow via custom_instruction; if you need plates ignored, no action is required — they are not classified as DRIVERS_LICENSE_NUMBER.

Nine-digit ambiguity: New York and Georgia licenses share their shape with SSNs. When scanning mixed HR files, request both DRIVERS_LICENSE_NUMBER and SSN; each hit is labeled by its own context, and you avoid the failure mode where an SSN-only scan silently absorbs license numbers or vice versa.

Frequently Asked Questions

Can the API tell which state issued a detected license number?

When the text names the state ("CA license", "issued in Ohio") the classification uses it, and the surrounding text keeps that attribution readable for your reviewers. The API does not guess a state from format alone — as the format table shows, several states share identical shapes, so a definitive attribution without context would be false precision.

How does detection avoid flagging VINs and policy numbers?

Through role classification: VINs appear near vehicle descriptors and are 17 characters; policy and claim numbers carry their own labels and document positions. The model assigns each token the role the sentence gives it. Where your internal identifiers are genuinely license-shaped, a one-line custom_instruction describing them eliminates the residual overlap.

Are commercial driver's licenses (CDLs) covered?

Yes. CDLs use the same state numbering systems, so they are detected identically; "CDL" labeling in fleet and logistics text is recognized vocabulary that raises confidence.

What about historical or legacy license numbers?

Old-format numbers (Washington's name-derived codes, Virginia's SSN-based legacy numbers) remain in archives and remain sensitive — Virginia's legacy numbers doubly so, since they may literally be SSNs. Legacy formats are in the training distribution and are detected; for SSN-derived ones, scan with both entity types enabled.

Does a lone 8-digit number ever get flagged?

Only when context supports it. A bare 38291045 in an invoice is ignored; the same number after "TX DL" or inside an MVR report is flagged with high confidence. This context dependence is deliberate — it is what keeps precision usable on identifier-dense business text.

Can I run this on non-English documents?

Yes — detection spans 60+ languages, including the label vocabulary around license numbers ("Führerscheinnummer", "numéro de permis", "número de licencia"). Coverage details are on the supported languages page.

How do I evaluate accuracy on my own data before buying?

Paste representative samples into the live demo — it runs the production models and shows each entity with type and confidence. Then take a free API key from get started and run a pilot batch; the pricing page lists volume tiers when you scale up.

Find Every License Number Hiding in Your Text

Test all 50 state formats against your own claims, tickets, and transcripts — no code required to start.

Try the Live Demo View Pricing