Both the Employer Identification Number (EIN) and Social Security Number (SSN) are nine-digit US identifiers, and both can show up in the same form — but they are issued by different authorities, have different formats, carry very different legal weight, and require different validation. This article walks through the differences that matter for developers: format, validation, generating safe test fixtures, and which identifier belongs in which form field.
The one-paragraph summary
An SSN identifies an individual person and is issued by the Social Security Administration (SSA). An EIN identifies a business entity and is issued by the IRS. Both are nine digits, but an EIN is written XX-XXXXXXX while an SSN is written XXX-XX-XXXX. Both look reasonable as raw 9-digit strings, which is why the format (and the issuing-authority checks behind it) is the easy way to distinguish them in code.
SSN — structure and rules
An SSN follows the format AAA-GG-SSSS with three components:
- Area (AAA): originally tied to the issuing state, with unused ranges reserved. Numbers 000, 666, and 900–999 are not assigned.
- Group (GG): within an area, issued in a documented ascending pattern. The group 00 is never used.
- Serial (SSSS): 0001–9999, sequential within a group.
The most important practical rule: certain area numbers are reserved and will never be assigned to a real individual. The most useful ranges for test data are 900-99-XXXX through 999-99-XXXX, which historically were issued for promotional purposes and remain unused. Our SSN Test Format generator uses these reserved area numbers so the output matches your regex but fails real-SSA validation.
EIN — structure and rules
An EIN follows the format XX-XXXXXXX:
- Prefix (XX): originally tied to the IRS campus that issued the number. After 2001 the prefix lets you determine the issuing branch, but it is not strictly tied to the company's location.
- Serial (XXXXXXX): a sequential 7-digit value.
Unlike SSN there is no public "reserved for testing" range, so generating fake EINs is about producing a 9-digit value that matches the format, often with a real-looking issuing prefix if your app tries to detect the IRS branch. Use the EIN Generator to emit plausible-looking synthetic EINs that will never collide with a real business.
Comparison table
| Property | EIN | SSN |
|---|---|---|
| Issued by | IRS | SSA |
| Identifies | Business entity | Individual person |
| Format | XX-XXXXXXX | AAA-GG-SSSS |
| Digits | 9 | 9 |
| Reserved-for-testing ranges | None official | 900–999 area numbers |
| PII sensitivity | High (business) | Very high (individual) |
| Storage regulation | Varies by context | Strongly regulated (GDPR, CCPA, IRS Pub 1075) |
Validation in regex
Format-only regex that accepts both identifier styles separately:
// EIN: XX-XXXXXXX (or 9 consecutive digits starting with non-zero)
const EIN_RE = /^\d{2}-\d{7}$/;
// SSN: AAA-GG-SSSS, area must avoid 000/666/900-999
const SSN_RE = /^(?!000|666|9\d\d)\d{3}-(?!00)\d{2}-(?!0000)\d{4}$/;
Note the negative lookaheads in the SSN pattern. They reject the never-issued ranges, so a validator built on this pattern will accept real SSNs (and reserved-area test SSNs depending on where you draw the line) and reject obvious junk. For tests, you often want the opposite — accept only the reserved 900–999 range — so you can guarantee that no real SSN ever lands in a staging DB. Flip the lookahead:
// Test-SSN only: AAA must be 900-999, GG != 00, SSSS != 0000
const TEST_SSN_RE = /^9\d{2}-(?!00)\d{2}-(?!0000)\d{4}$/;
JavaScript validator with auto-detection
function classifyIdentifier(value) {
const v = String(value).replace(/\D/g, "");
if (v.length !== 9) return { type: null, error: "must be 9 digits" };
const fmt = `${v.slice(0, 2)}-${v.slice(2)}`;
if (EIN_RE.test(fmt)) {
return { type: "EIN", formatted: fmt };
}
const ssn = `${v.slice(0, 3)}-${v.slice(3, 5)}-${v.slice(5)}`;
if (SSN_RE.test(ssn)) return { type: "SSN", formatted: ssn };
return { type: null, error: "format mismatch" };
}
This is the safest auto-detect approach. Real SSNs and EINs both pass format validation; the choice of which input you collect on your form is a business decision, not a parsing trick.
When to use which in your forms
Use an SSN field when…
- You are collecting from individuals for credit, employment, or tax-withholding purposes (e.g., payroll onboarding, tenant screening, loan applications).
- Your compliance team has explicitly authorized SSN storage with appropriate encryption, access controls, and a documented data-retention policy.
Use an EIN field when…
- You are onboarding a business as a customer, merchant, or sub-contractor (W-9 collection, B2B SaaS signup, payment processor KYB).
- You need to send 1099-MISC or 1099-NEC reports to the IRS about that entity.
Never mix expecting both in one field
A "Tax ID" input that silently accepts either an SSN or EIN is a UX trap — the form will not know what compliance rules to apply and your data team will not know whether a record is a person or a business. Use separate inputs.
Generating safe fakes for tests
The guiding rule: test data must never validate against the live system. For SSNs that means drawing from the 900–999 area range that the SSA has publicly confirmed is unused. For EINs there is no equivalent IRS ruleset, so every EIN your form accepts is potentially a real business identifier — never store a randomly generated EIN in a system that calls the IRS or a third-party KYB vendor.
// Pull safe test SSN
fetch("/us-address/api/v1/ssn?count=10", {
headers: { Authorization: `Bearer ${KEY}` }
})
.then(r => r.json())
.then(res => res.data); // 10 reserved-area SSNs
// Pull synthetic EINs (format-only)
fetch("/us-address/api/v1/ein?count=10", {
headers: { Authorization: `Bearer ${KEY}` }
})
.then(r => r.json());
Both outputs look credible to your form and pass your regex, but the SSN values fail real-SSA validation and the EIN values are random strings unlikely to collide with an actual business.
Compliance notes worth knowing
If your application stores either identifier, you are likely subject to specific regulations:
- GLBA and state breach laws treat both SSN and EIN as personal information in many jurisdictions.
- IRS Publication 1075 defines handling rules for federal tax information, including SSNs.
- GDPR: an SSN of any nationality is special-category personal data and requires lawful basis plus protection by design.
- PCI DSS does not directly govern SSN/EIN, but if either identifier appears next to cardholder data your scope expands.
Before shipping a form that collects an SSN or EIN, confirm with your legal and security teams that the storage, encryption, access logging, and retention policy are documented. If they are not, generate test data and build the form, but do not flip the switch to production storage until they are.
Wrapping up
The TL;DR for developers: SSN identifies a person, EIN identifies a business, both are 9 digits with different formats, both are sensitive — but SSN is far more regulated. Validate them separately, collect them in separate fields, and when you test, pull from the SSA's reserved SSN range (via the SSN Test Format tool) and from format-only synthetic EINs (the EIN Generator). That keeps your fixtures exercising every regex branch without ever risking a real person's data.