colinhacks /zod

TypeScript-first schema validation with static type inference

★ 44,302⑂ 2,331👁 78⑃ 2,210● 3,294▤ 218◈ 1,133
TypeScriptMITCreated 2020-03-07zod.dev
44,302
stars
+5
2,331
forks
78
watchers
2,210
prs
3,294
issues
218
releases
1,133
discussions

README

Zod
  
    TypeScript-first schema validation with static type inference
    
    by @colinhacks
  












  Docs
    •  
  Discord
    •  
  𝕏
    •  
  Bluesky
  





 Read the docs →




 What is Zod?

Zod is a TypeScript-first validation library. Define a schema and parse some data with it. You'll get back a strongly typed, validated result.

ts
import  as z from "zod";

const User = z.object({
  name: z.string(),
});

// some untrusted data...
const input = {
  / stuff /
};

// the parsed result is validated and type safe!
const data = User.parse(input);

// so you can use it with confidence :)
console.log(data.name);




 Features

- Zero external dependencies
- Works in Node.js and all modern browsers
- Tiny: 2kb core bundle (gzipped)
- Immutable API: methods return a new instance
- Concise interface
- Works with TypeScript and plain JS
- Built-in JSON Schema conversion
- Extensive ecosystem



 Installation

sh
npm install zod




 Basic usage

Before you can do anything else, you need to define a schema. For the purposes of this guide, we'll use a simple object schema.

ts
import  as z from "zod";

const Player = z.object({
  username: z.string(),
  xp: z.number(),
});


 Parsing data

Given any Zod schema, use .parse to validate an input. If it's valid, Zod returns a strongly-typed _deep clone_ of the input.

ts
Player.parse({ username: "billie", xp: 100 });
// = returns { username: "billie", xp: 100 }


Note — If your schema uses certain asynchronous APIs like async refinements or transforms, you'll need to use the .parseAsync() method instead.

ts
const schema = z.string().refine(async (val) = val.length  "hello"


 AOT compilation

For hot validation paths, z.compile(schema) returns a schema clone with an ahead-of-time compiled fast path. Valid inputs take the compiled path; invalid inputs fall back to the regular parser so error reporting stays identical.

Across a 55-schema benchmark the median speedup is 2.4x, and it scales with how much work the schema does per parse: a large array of objects is ~9x, a 20-key object ~9x, a nested object ~4.5x, while a bare z.string() gains nothing — compilation removes per-node dispatch and allocation, and a single typeof has none to remove.

ts
const CompiledPlayer = z.compile(Player);

CompiledPlayer.parse({ username: "billie", xp: 100 });


To enable compilation globally for schemas constructed after import:

ts
import "zod/compile"; // place before modules that define schemas


Things to know:

- Compilation uses new Function. Global mode is automatically disabled when z.config({ jitless: true }) is set (e.g. CSP environments); calling z.compile() directly is an explicit opt-in.
- Schemas with async refinements or transforms can't be compiled, and neither can a few other constructs. That is not an error: z.compile() hands the schema back unchanged and it keeps using the regular parser, exactly as global mode leaves it. Pass { s

Top issues

Discussions

Latest release

v4.6.7 v4.6.7 2026-10-12
Commits:

- b500a2ee95134f81d74da7911d7378dd2853d042 4.6.7

Snapshot: 2026-11-10T09:35:25Z · Data license Apache-2.0 · JSON