/^/
MediumSecurity5 min read

US Social Security Number Regex

Validates the format of a US Social Security Number (123-45-6789), rejecting area, group, and serial values that the SSA never issues, such as area 000, 666, or 900-999.

#ssn#security#identity#validation#usa#pii

Regex Pattern

^(?!000|666|9\d{2})\d{3}-(?!00)\d{2}-(?!0000)\d{4}$

Pattern Breakdown

Hover over a token to see what it does.

^(?!000|666|9\d{2})\d{3}-(?!00)\d{2}-(?!0000)\d{4}$
TokenMeaning
^Anchors the match to the start of the string
(?!000|666|9\d{2})Negative lookahead rejecting area numbers 000, 666, or any number starting with 9 (900-999), which the SSA never assigns
\d{3}-The 3-digit area number followed by a literal hyphen
(?!00)\d{2}-Negative lookahead rejecting group '00', then the 2-digit group number and a hyphen
(?!0000)\d{4}$Negative lookahead rejecting serial '0000', then the 4-digit serial number and end of string

Detailed Explanation

What it does

This pattern validates that a string is in the standard AAA-GG-SSSS Social Security Number format while also rejecting known-invalid combinations: an area of 000, 666, or 900-999, a group of 00, or a serial of 0000, none of which the Social Security Administration has ever issued.

Why it works

Each `(?!...)` is a zero-width negative lookahead placed immediately before the digits it constrains, so it can reject a disallowed value before the corresponding `\d{n}` consumes it, without affecting what actually gets matched. Chaining three independent lookahead/digit-group pairs mirrors the SSA's own historical issuance rules segment by segment.

Common use cases

  • Format-validating SSN input fields on US tax, payroll, or benefits enrollment forms
  • Client-side pre-checks before submitting sensitive PII to a backend for encrypted storage
  • Filtering documents or logs for SSN-shaped strings during a PII redaction pass
  • Rejecting obviously fake test data like 000-00-0000 in QA environments

Edge cases

  • Since 2011 the SSA uses randomized issuance, so the old geographic meaning of the area number no longer applies, but the never-issued ranges (000, 666, 900-999) are still permanently invalid
  • SSNs without hyphens, like '123456789', are rejected by this pattern since it requires the hyphenated display format
  • The famous placeholder '078-05-1120' (originally a sample SSN misused by many people) passes format validation despite widespread real-world misuse
  • A format-valid SSN like '123-45-6789' may still not belong to any real person; this pattern cannot check issuance records

Limitations

  • Cannot verify an SSN was actually issued or belongs to the claimed individual (needs SSA's official verification service)
  • Does not detect known-compromised or breached SSNs
  • Only validates the hyphenated display format; a companion pattern is needed for the unformatted 9-digit form
  • Handling and storing SSNs requires strict security and compliance controls well beyond regex validation

Interactive Tester

Edit the pattern or text below — matching runs live in your browser.

123-45-6789 078-05-1120

Test Cases

Editable — add your own inputs to see if they pass.

InputExpectedResult
Pass
Pass
Pass
Pass
Pass
Pass
Pass
Pass

Language Variants

Production-ready examples in 12 languages.

const ssnRegex = /^(?!000|666|9\d{2})\d{3}-(?!00)\d{2}-(?!0000)\d{4}$/;
console.log(ssnRegex.test('123-45-6789')); // true

Common Mistakes

Assuming Go's or Rust's built-in regex engines support the negative lookaheads used here

Fix: RE2-based engines don't support lookahead; capture the digit groups and check the invalid ranges with plain string comparisons instead

Validating format only and treating a passing SSN as proof of identity

Fix: Format validation should be paired with proper KYC/identity verification, never used as identity proof on its own

Logging or storing SSNs in plaintext after validation for debugging

Fix: Mask all but the last 4 digits in logs and encrypt SSNs at rest per PII handling requirements

Performance Notes

  • The negative lookaheads only inspect a few characters ahead each time, so they add negligible overhead over a plain digit-and-hyphen match
  • Fixed-width digit groups mean no catastrophic backtracking is possible in this pattern
  • Precompile and reuse the regex object across requests instead of recompiling per validation call

Browser Compatibility

EngineSupportedNotes
ChromeYes
FirefoxYes
SafariYes
EdgeYes
Node.jsYes