vld.

Validation, with everything it didn't need removed. The Zod API you already write, zero dependencies, and about three times the speed.

See the one-line migration

Every value above is checked live by @oxog/vld in this tab. Rejections speak one of its 32 locales.

gate z.string().email()checked 0rejected 0

  • enInvalid email address
  • trMetin en az 3 karakter olmalı
  • esEl número debe ser positivo
  • frURL invalide
  • deUngültige E-Mail-Adresse
  • itLa stringa deve avere almeno 3 caratteri
  • ptNúmero deve ser positivo
  • ruНекорректный URL
  • ja無効なメールアドレス
  • ko문자열은 최소 3자여야 합니다
  • zh数字必须是正数
  • arرابط غير صحيح
  • hiअमान्य ईमेल पता
  • nlString moet ten minste 3 tekens lang zijn
  • plLiczba musi być dodatnia
  • daUgyldig URL
  • svOgiltig e-postadress
  • noStreng må være minst 3 tegn lang
  • fiLuvun tulee olla positiivinen
  • thURL ไม่ถูกต้อง
  • viĐịa chỉ email không hợp lệ
  • idString harus memiliki minimal 3 karakter
  • bnসংখ্যাটি ধনাত্মক হতে হবে
  • guઅમાન્ય URL
  • knಅಮಾನ್ಯ ಇಮೇಲ್ ವಿಳಾಸ
  • neस्ट्रिङ कम्तीमा 3 अक्षरहरूको हुनुपर्छ
  • skČíslo musí byť kladné
  • swURL si sahihi
  • afOngeldige e-pos adres
  • tgСатр бояд ҳадди ақал 3 аломат дошта бошад
  • pt-BRNúmero deve ser positivo
  • es-MXURL inválida
  • enNumber must be positive
  • trGeçersiz URL
  • esDirección de correo inválida
  • frLa chaîne doit contenir au moins 3 caractères
  • deNummer muss positiv sein
  • itURL non valido
  • ptEndereço de email inválido
  • ruСтрока должна содержать не менее 3 символов
  • ja数値は正の値である必要があります
  • ko유효하지 않은 URL
  • zh无效邮箱地址
  • arيجب أن يحتوي النص على 3 حرف على الأقل
  • hiसंख्या सकारात्मक होनी चाहिए
  • nlOngeldige URL
  • plNieprawidłowy adres email
  • daStreng skal være mindst 3 tegn lang
  • svNummer måste vara positivt
  • noUgyldig URL
  • fiVirheellinen sähköpostiosoite
  • thข้อความต้องมีความยาวอย่างน้อย 3 ตัวอักษร
  • viSố phải là số dương
  • idURL tidak valid
  • bnঅবৈধ ইমেইল ঠিকানা
  • guસ્ટ્રિંગ ઓછામાં ઓછા 3 અક્ષરોની હોવી જોઈએ
  • knಸಂಖ್ಯೆ ಧನಾತ್ಮಕವಾಗಿರಬೇಕು
  • neअमान्य URL
  • skNeplatná e-mailová adresa
  • swMfuatano lazima uwe na angalau vibambo 3
  • afGetal moet positief wees
  • tgURL нодуруст аст
  • pt-BREndereço de e-mail inválido
  • es-MXLa cadena debe tener al menos 3 caracteres

Change one line. Keep the rest.

vld follows Zod's API and error shapes, so moving over means pointing your import at a new package. Schemas, inferred types and error handling stay as they are.

  • Every public Zod 4.6 export, all 259 of them, is checked against each release.
  • A 1,400-case behavior sweep compares results with the installed zod.
  • Zod's entry points are mirrored: /v4, /v4-mini, /v4/core, /v4/locales.
  • toZodError() hands existing tooling the ZodError shape, with .format() and .flatten().
signup.tsediting
import { z } from 'zod';
const signup = z.object({
  name: z.string().min(2).max(100),
  email: z.string().email(),
  age: z.number().int().positive().optional(),
  role: z.enum(['admin', 'user', 'guest']).default('user'),
});

type Signup = z.infer<typeof signup>;

const result = signup.safeParse(input);
if (!result.success) {
  console.log(result.error.flatten().fieldErrors);
}

Don't take our numbers. Make your own.

Both libraries are bundled into this page. The button runs the same schemas on the same data, alternating between them in short slices, on your hardware.

Takes about ten seconds. Runs in a Web Worker, so the page stays responsive.

  1. z.string().min(1).email()input "ada@lovelace.dev"
    vld
    —
    zod
    —
    —
  2. z.number().int().positive()input 42
    vld
    —
    zod
    —
    —
  3. z.union([z.string(), z.number(), z.boolean()])input true
    vld
    —
    zod
    —
    —
  4. z.string().optional()input undefined
    vld
    —
    zod
    —
    —
  5. z.object({ id, name, email, active, tags })input { id: 1, name: "Ada", … }
    vld
    —
    zod
    —
    —

What CI holds every release to

Speed ratios against Zod on Node. A release that falls below its floor doesn't ship.

  • Nullish30.7×
  • Positive integer9.1×
  • Discriminated union4.1×
  • Optional3.8×
  • Union3.3×
  • Simple string3.0×
  • Array and object1.7×

Errors your users can actually read.

32 locales ship with the package, from Türkçe to Kiswahili. Load them lazily with setLocaleAsync() and only the language you use ends up in the bundle.

z.object({
  name: z.string().min(2),
  email: z.string().email(),
  age: z.number().int().positive(),
  website: z.string().url().optional(),
})
Messages in
  • nameMetin en az 2 karakter olmalı
  • emailGeçersiz e-posta adresi
  • ageSayı pozitif olmalı
  • websiteGeçersiz URL

Messages come from setLocale('tr'). Fix the input and watch them clear.

More than parse and safeParse.

Zod 4.6’s .validate() answers yes or no without building a result object. vld compiles the schema ahead of time on first call.

const isUser = userSchema.validate(payload);   // true | false

// Async refinements work too
await userSchema.validateAsync(payload);

Swap the import. Ship lighter.

MIT licensed, zero dependencies, Node 18 and up, every modern browser.