npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

us-ssn-tools

v2.0.0

Published

Validate, format, mask, and generate US social security numbers

Readme

US Social Security Tools

A small, well-tested TypeScript library for working with U.S. Social Security Numbers (SSNs) in UI and backend code.

It provides:

  • Validation (strict + typing-as-you-go, boolean API)
  • 🔁 Normalization (deterministic, UI-friendly formatting)
  • 🎭 Masking (privacy-first, best-effort, never validates)
  • 🎲 Generation (pre-2011, post-2011, random, and publicly advertised SSNs)
  • 🧩 Zod & Yup adapters for form validation

Design principles

  • Validation answers “is this valid?” — nothing more.
  • Normalization formats input for display and typing UX.
  • Masking never leaks digits and never enforces validity.
  • Public safety beats convenience.

Installation

npm install us-ssn-tools

or

yarn add us-ssn-tools

Imports

import {
  isValidSsn,
  normaliseSsn,
  formatSsnFromDigits,
  maskSsn,
  generateSsn,
} from "us-ssn-tools";

import { zodSsnTyping, zodSsnSubmit } from "us-ssn-tools/zod";
import { yupSsnTyping, yupSsnSubmit } from "us-ssn-tools/yup";

Validation

isValidSsn(input, options): boolean

Checks whether an SSN is valid according to U.S. rules.

  • Returns true or false only
  • Does not normalize
  • Can validate partial input (“valid so far”)
isValidSsn("123-45-6789"); // true
isValidSsn("123456789");  // false (dashes required by default)

Options

type ValidateSsnOptions = {
  requireDashes?: boolean;   // default: true
  allowPartial?: boolean;    // default: false
  ruleMode?: "pre2011" | "post2011"; // default: "post2011"
};

Examples

isValidSsn("9", { allowPartial: true });
// true (still potentially valid)

isValidSsn("900", { allowPartial: true });
// false (invalid area)

isValidSsn("773-12-3456", { ruleMode: "pre2011" });
// false

isValidSsn("773-12-3456", { ruleMode: "post2011" });
// true

Normalization

normaliseSsn(input, options): string

Formats input for UI display. It does not validate and never throws.

  • Extracts digits
  • Optionally inserts dashes
  • Supports typing-as-you-go
  • Allows overflow digits if desired
normaliseSsn("1234");        // "123-4"
normaliseSsn("123456789");  // "123-45-6789"
normaliseSsn("SSN: 12a3");  // "123"

Options

type NormaliseSsnOptions = {
  allowPartial?: boolean;  // default: true
  digitsOnly?: boolean;    // default: false
  enforceLength?: boolean; // default: false
};

Examples

normaliseSsn("123456789", { digitsOnly: true });
// "123456789"

normaliseSsn("12345678999");
// "123-45-678999"

normaliseSsn("12345678999", { enforceLength: true });
// "123-45-6789"

Formatting (UI helper)

formatSsnFromDigits(digits)

Formats a digit string into SSN shape.

formatSsnFromDigits("123");       // "123"
formatSsnFromDigits("1234");      // "123-4"
formatSsnFromDigits("123456789"); // "123-45-6789"

No validation is performed.


Masking (UI-safe)

maskSsn(input, options): string

Masks digits after normalization.

  • Always normalizes first
  • Never validates
  • Never reveals digits unless explicitly allowed
  • Safe for any UI context
maskSsn("123-45-6789");
// "***-**-****"

maskSsn("123-45-6789", { revealLast4: true });
// "***-**-6789"

Options

type MaskSsnOptions = {
  allowPartial?: boolean;   // default: true
  revealLast4?: boolean;    // default: false
  maskChar?: string;        // default: "*"
  digitsOnly?: boolean;     // default: false
  enforceLength?: boolean;  // default: false
};

Typing behavior

maskSsn("123"); 
// "***"

maskSsn("123-45-6", { revealLast4: true });
// "***-**-6"

Guarantees

  • ✔️ Digits are always masked
  • ✔️ Dashes are never masked
  • ✔️ Invalid input is still safely masked
  • ✔️ No validation logic inside masking

Generation

generateSsn(options): string

Generates SSNs for testing and development.

generateSsn();
// one of the publicly advertised SSNs

Options

type GenerateSsnOptions = {
  mode?: "public" | "pre2011" | "post2011" | "any"; // default: "public"
  digitsOnly?: boolean; // default: false
};

⚠️ Important note on public usage

Only use mode: "public" for any SSNs that may be displayed publicly.

SSNs generated with "pre2011", "post2011", or "any" are syntactically valid and may correspond to real individuals.

If such values are:

  • shown in documentation
  • used in screenshots
  • logged publicly
  • included in demos or examples

you risk exposing a real person to identity theft.

The "public" mode returns historically documented, publicly advertised SSNs that are known to be unsafe for real-world use but safe for examples.

// ✅ Safe for docs, demos, screenshots
generateSsn({ mode: "public" });

// ❌ Never display publicly
generateSsn({ mode: "any" });
generateSsn({ mode: "pre2011" });
generateSsn({ mode: "post2011" });

Zod Adapters

Typing (partial + normalized)

const schema = zodSsnTyping();

schema.parse("1234"); // "123-4"
schema.parse("900");  // ❌ throws

Submit (strict)

const schema = zodSsnSubmit();

schema.parse("123456789"); // "123-45-6789"
schema.parse("123-45-6");  // ❌ throws

Yup Adapters

await yupSsnTyping().validate("1234");
// "123-4"

await yupSsnSubmit().validate("123456789");
// "123-45-6789"

Testing & Guarantees

  • ✔️ Extensive table-driven Jest tests

  • ✔️ Clear separation between:

    • validation
    • normalization
    • masking
    • generation
  • ✔️ UI-safe defaults everywhere


Non-Goals

  • ❌ No storage or encryption
  • ❌ No non-US SSNs (yet)
  • ❌ No mutation of user input beyond formatting

License

ISC


Support This Project

If you find this project useful, consider supporting it:

Your support is greatly appreciated 🙏