zod email validation

Zod email validation

Validate email addresses in Zod 4 with the top-level z.email(), add custom messages, choose a stricter pattern, and migrate from the deprecated z.string().email().

Open the JSON to Zod converter

Quick answer: how do you validate an email in Zod 4?

Use the top-level `z.email()`. In Zod 4 the email validator moved from `z.string().email()` to a dedicated `z.email()` schema, which is the recommended form. The old method still works but is deprecated, so prefer `z.email()` in new code.

Basic email validation

Use `z.email()` directly as a field schema. It rejects values that are not valid email addresses and returns the typed string when they are.

import * as z from "zod";

const SignupSchema = z.object({
  email: z.email(),
  password: z.string().min(8),
});

SignupSchema.parse({ email: "jane@acme.dev", password: "hunter2!" });

Custom error messages

Pass an options object (or a string) to set the message shown when validation fails. This is the value you typically render next to the input.

const EmailField = z.email({ error: "Enter a valid email address" });

const result = EmailField.safeParse("not-an-email");
if (!result.success) {
  result.error.issues[0].message; // "Enter a valid email address"
}

Choose a stricter or unicode pattern

Email validity is famously fuzzy. Zod 4 lets you pass a `pattern` so you can match a specific standard, such as the HTML5 input pattern or a unicode-aware one, instead of the default.

// HTML5 input-style validation
const html5 = z.email({ pattern: z.regexes.html5Email });

// Accept unicode local parts
const unicode = z.email({ pattern: z.regexes.unicodeEmail });

Migrate from z.string().email()

If you are upgrading from Zod 3, the chained method is deprecated but still runs. Replace it with the top-level schema as you touch each field; combine with other string rules by chaining on the email schema.

// Before (deprecated in Zod 4)
const oldEmail = z.string().email().max(254);

// After
const newEmail = z.email().max(254);

Email validation in Zod 4

ApproachWhat it doesUse when
z.email()Top-level email schema in Zod 4 with a sensible default pattern.New code validating an email field.
z.email({ error: "..." })Same validation with a custom error message.You surface the message directly to users.
z.email({ pattern: z.regexes.html5Email })Swaps in a specific regex such as the HTML5 or unicode pattern.You need to match a particular standard or accept unicode addresses.
z.string().email()Legacy v3 style, deprecated in Zod 4.Only in older code you have not migrated yet.

Use FrameworkKit to generate the starter code, then review the output before shipping it in production.

Generate with the JSON to Zod schema generator

Zod validation resources

JSON to Zod converter

Convert sample payloads into copy-ready Zod schemas and inferred TypeScript types in the browser.

JSON to Zod schema examples

Open realistic API and product payload examples before adapting the JSON to Zod schema output.

TypeScript to Zod Converter

Convert TypeScript interfaces and type aliases into Zod schemas when the source shape already lives in code.

Zod to JSON Schema Converter

Use the canonical online converter when an existing Zod schema needs JSON Schema, AJV, or OpenAPI output.

Validate API responses with Zod

Validate API responses, request bodies, and fetch boundaries with Zod schemas in TypeScript.

Zod parse vs safeParse

Choose between parse, safeParse, parseAsync, and safeParseAsync for TypeScript validation flows.

Zod safeParse

Validate unknown data without throwing, narrow the result type, and format safeParse errors.

Zod safeParse error messages

Format safeParse failures, field errors, and API validation responses in TypeScript.

Zod refine vs superRefine

Add custom validation, async checks, and field-level error paths after generating a starter schema.

Zod nativeEnum in Zod 4

Migrate z.nativeEnum patterns to z.enum, validate TypeScript enums, and avoid enum value mistakes.

Use JSON to Zod for form validation

Start from a submitted form payload, then add business rules such as email, length, and enum checks.

Zod to JSON Schema for OpenAPI

Publish Zod API schemas as OpenAPI-compatible contracts when teams need portable documentation.

ZodError flatten vs format

Shape validation errors with z.flattenError() for forms and z.treeifyError() for nested data in Zod 4.

Zod coerce for query params

Turn string query params and form fields into numbers, dates, and booleans, and avoid the coerce.boolean trap.

Zod transform and pipe

Reshape validated data with transform, chain a second check with pipe, and use z.codec for reversible conversions.

Zod vs JSON Schema

Choose between TypeScript-first runtime validation and portable schema contracts.

Zod vs Yup vs Valibot

Compare TypeScript validation libraries for API boundaries, forms, server actions, and bundle tradeoffs.

FAQ

Is z.string().email() deprecated in Zod 4?

Yes. Zod 4 introduces the top-level `z.email()` schema as the recommended form. The chained `z.string().email()` still works but is deprecated, so prefer `z.email()` in new code.

How do I set a custom email error message?

Pass options to the validator, for example `z.email({ error: "Enter a valid email address" })`. The message appears on the failing issue.

Can I use a stricter email regex?

Yes. Pass a `pattern`, such as `z.email({ pattern: z.regexes.html5Email })`, to match a specific standard or accept unicode addresses.

How do I combine email with other rules like max length?

Chain on the email schema, for example `z.email().max(254)`, the same way you would add length or transform rules to any string schema.

Related tools