mrkeyoor.com_
Thu 06 Aug 01:04 UTC
npmUtilsupdated 05 Aug 2026

ajv-formats

ajv-formats is the official plugin that gives Ajv v8 its format keyword validators. Ajv 8 removed built-in formats from the core, so a bare new Ajv() throws on format: 'email' in strict mode. One call, addFormats(ajv), registers the JSON Schema draft formats (date, time, date-time, duration, uri, uri-reference, email, hostname, ipv4, ipv6, uuid, regex, json-pointer) plus the OpenAPI data types (int32, int64, float, double, byte, binary, password). It also adds formatMinimum and formatMaximum keywords for range checks on dates and times.

Verdict

If you run Ajv 8 with format keywords, this is not optional; install it and move on. Just know it is in low-maintenance mode and treat format checks as annotations with teeth, not as input security.

API stability5/5The entire API is one default export plus an options object; v3 has been current since early 2024 and format definitions have not changed, so upgrades are non-events.
Docs3/5The README lists every format and option, but behavioral details (what fast mode actually skips, exact regexes) require reading formats.ts, and the comparison keywords section is dense; deeper concepts live in Ajv's own docs.
Maintenance2/5Last publish March 2024, last push August 2024, 53 open issues plus more PRs; nothing has broken, but nothing gets fixed either, and the whole Ajv org has slowed.
Ecosystem5/5120.1M weekly downloads riding Ajv's ubiquity; webpack's schema-utils and much of the Fastify ecosystem pull it in transitively, so it is already in most node_modules trees.

Use it if

  • You use Ajv 8 with any schema containing format; without this plugin strict-mode Ajv throws 'unknown format' at compile time
  • You validate OpenAPI 3.0 schemas, which lean on int32, int64, float, double, and byte formats that plain JSON Schema lacks
  • You need date or time range validation declaratively: formatMinimum and formatExclusiveMaximum compare values within a format's ordering
  • You want control over bundle size and behavior: you can register only the formats you use, and switch to fast mode for cheaper regexes
Skip it if

Setup reality

npm install ajv ajv-formats; the plugin declares ajv ^8.0.0 as both a dependency and an optional peer, so the real risk is two ajv copies in the tree, which produces baffling 'unknown keyword' or type mismatch errors until you dedupe. TypeScript under NodeNext module resolution hits the classic Ajv dual-package problem where the default import needs esModuleInterop or a .default call. And if you use the 2020-12 dialect you must instantiate Ajv2020 from ajv/dist/2020 and pass that instance to addFormats; the plain Ajv class only speaks draft-07.

Patterns

Register all formats on an Ajv instanceadd-all-formats

import Ajv from "ajv";
import addFormats from "ajv-formats";

const ajv = new Ajv();
addFormats(ajv);

const validate = ajv.compile({ type: "string", format: "email" });
validate("a@b.co");  // true

Call addFormats before compiling any schema that uses format. In CommonJS use const addFormats = require("ajv-formats").

Validate email, uuid, and uri fields in one schemavalidate-common-formats

const schema = {
  type: "object",
  properties: {
    id: { type: "string", format: "uuid" },
    email: { type: "string", format: "email" },
    website: { type: "string", format: "uri" },
  },
  required: ["id", "email"],
};
const validate = ajv.compile(schema);
if (!validate(data)) console.log(validate.errors);

format only applies to strings; a numeric value passes a format check untouched because JSON Schema defines format per type.

Register only the formats you useregister-only-needed-formats

addFormats(ajv, ["date-time", "uuid"]);

Any other format in your schemas will now throw at compile time under strict mode, which is a feature: it catches typos like 'datetime'.

Trade correctness for speed with fast modefast-mode

addFormats(ajv, { mode: "fast" });

Fast mode simplifies date, time, date-time, uri, uri-reference, and email: dates stop range-checking, so 2026-02-31 passes structure-only validation. Only use it where inputs are already trusted.

Range-check dates with formatMinimum/formatMaximumdate-range-keywords

const schema = {
  type: "string",
  format: "date",
  formatMinimum: "2026-01-01",
  formatExclusiveMaximum: "2027-01-01",
};
const validate = ajv.compile(schema);
validate("2026-08-05");  // true
validate("2027-01-01");  // false

These keywords are only registered when addFormats runs with no options or with keywords: true; if you pass any options object, remember to include keywords: true or compilation throws.

Use formats with the 2020-12 dialectdraft-2020-dialect

import Ajv2020 from "ajv/dist/2020";
import addFormats from "ajv-formats";

const ajv = new Ajv2020();
addFormats(ajv);

The default Ajv class is draft-07. Schemas declaring $schema 2020-12 need the Ajv2020 class, and addFormats works on it the same way.

Allow formats you intentionally do not validateallow-unknown-formats

const ajv = new Ajv({ formats: { "customer-code": true } });
addFormats(ajv);

Mapping a format name to true makes Ajv accept it as a no-op instead of throwing in strict mode; useful for vendor schemas with proprietary formats.

date-time requires a timezone; iso-date-time does notdate-time-timezone-gotcha

addFormats(ajv, ["date-time", "iso-date-time"]);

const strict = ajv.compile({ type: "string", format: "date-time" });
strict("2026-08-05T12:00:00");        // false, no timezone
strict("2026-08-05T12:00:00Z");       // true

const loose = ajv.compile({ type: "string", format: "iso-date-time" });
loose("2026-08-05T12:00:00");         // true

RFC 3339 date-time mandates an offset or Z. Local timestamps from HTML datetime-local inputs fail it; validate those with iso-date-time instead.

Validate OpenAPI integer formatsopenapi-number-formats

const schema = {
  type: "object",
  properties: {
    count: { type: "integer", format: "int32" },
    total: { type: "integer", format: "int64" },
  },
};

int64 checks the value is an integer in range, but JavaScript numbers lose precision past 2^53, so a true 64-bit ID has already been corrupted by JSON.parse before validation sees it; keep big IDs as strings.

Add your own format next to the standard onescustom-format-alongside

addFormats(ajv);
ajv.addFormat("semver", /^\d+\.\d+\.\d+(-[\w.]+)?$/);

const validate = ajv.compile({ type: "string", format: "semver" });
validate("1.2.3");  // true

ajv.addFormat is core Ajv, not this plugin, and both register into the same namespace; defining a format twice overwrites silently, so avoid reusing standard names.

Alternatives

PackageRegistryPick it when
ajv-formats-draft2019npmYou need the internationalized formats: iri, idn-email, idn-hostname
@cfworker/json-schemanpmYou need JSON Schema validation with formats included in environments that block code generation, like Cloudflare Workers
zodnpmTypeScript-first validation with inferred types and no JSON Schema requirement
joinpmYou prefer a chainable schema builder for Node config and request validation