Skip to content

JSON Schema Validator

Validate JSON against any JSON Schema instantly in your browser. Supports Draft 2020-12, 2019-09, and Draft-07 with path-precise error messages. 100% private — no upload, no account, free.

No Tracking Runs in Browser Free
Paste both JSON data and a schema
Reviewed for Draft 2020-12, 2019-09, and Draft-07 compliance, including type coercion edge cases, format vocabulary, $ref resolution, and JSON Pointer error paths. — Go Tools API Tooling Team · May 7, 2026

What is a JSON Schema Validator?

A JSON Schema validator is a program that takes two JSON documents — a data document and a schema document — and reports whether the data conforms to the schema's contract. The schema declares field types, required keys, value ranges, allowed enum values, regex patterns, and structural rules using a fixed vocabulary (type, properties, required, items, enum, oneOf, allOf, $ref, format). The validator walks both documents in parallel and emits zero or more errors, each pinned to a JSON Pointer path inside the data.

Validation runs at runtime, at the boundary between untrusted input and your code. TypeScript types vanish at compile time and cannot help with JSON arriving from a webhook, a third-party API, or a user paste — that gap is exactly what JSON Schema fills. Pair it with TypeScript (or Pydantic in Python) and you get compile-time guarantees inside your codebase plus runtime guarantees at the boundary.

Draft 2020-12 is the current spec and what you should pick for new projects in 2026. Earlier drafts (2019-09, Draft-07, Draft-06, Draft-04) survive in legacy codebases — Draft-07 is still common in Helm charts, VS Code settings, and older Ajv configs. OpenAPI 3.1 uses Draft 2020-12 natively; OpenAPI 3.0 uses a Draft 4 subset.

This tool runs entirely in your browser. Your JSON, your schema, and the validation output never leave your machine — safe for proprietary API contracts and sensitive payloads. Internal $ref pointers resolve automatically; external HTTP refs are intentionally disabled to preserve privacy.

Working with adjacent JSON tools? Format the JSON with JSON Formatter before pasting; compare two JSON documents with JSON Diff; convert with JSON to YAML and YAML to JSON. For end-to-end validation in Node, Python, and the browser, see our JSON Schema validation guide.

// A 5-line schema that catches three real bugs
const schema = {
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "id":    { "type": "integer", "minimum": 1 },
    "email": { "type": "string", "format": "email" },
    "age":   { "type": "integer", "minimum": 0, "maximum": 150 }
  },
  "required": ["id", "email"],
  "additionalProperties": false
};

// Three bugs the schema catches:
const bad = { "id": "42", "age": 200 };
//   /id   → type: expected integer, got string
//   /email → required: missing
//   /age   → maximum: 200 > 150

// In Node:        new Ajv().compile(schema)(bad)  // false; ajv.errors has the paths
// In Python:      jsonschema.validate(bad, schema)
// In the browser: this tool — same errors, same paths, no install

Key Features

Multi-Draft Support

Draft 2020-12 (default), 2019-09, and Draft-07. Auto-detects the draft from the schema's $schema URI; fallback selector for schemas without one.

Path-Precise Errors

Every error includes a JSON Pointer (e.g. /user/email/0), the failing keyword (type, required, pattern), and a one-line message. Click to jump to the location.

Live Validation

Validates as you type. Errors update in real time so you can iterate on the schema or the data without round-tripping through Validate buttons.

Format Keyword Coverage

email, uri, uuid, date, date-time, ipv4, ipv6, hostname, regex — the formats you actually use, validated with battle-tested patterns.

100% Browser-Based

Inputs never leave your machine. No upload, no analytics on what you paste, no localStorage of JSON. Safe for proprietary contracts and sensitive payloads.

Sample Schemas, One Click

Loadable presets (signup form, webhook envelope, config file, array of orders) get you to a working validation in under five seconds.

Examples

Valid Object — required + types

{
  "id": 42,
  "email": "alice@example.com",
  "age": 30
}
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "id": { "type": "integer", "minimum": 1 },
    "email": { "type": "string", "format": "email" },
    "age": { "type": "integer", "minimum": 0, "maximum": 150 }
  },
  "required": ["id", "email"],
  "additionalProperties": false
}

Schema declares id and email as required and pins types. The data above passes — every constraint is satisfied. Try removing email or changing id to a string to see path-precise errors.

Invalid — missing required + wrong type

{
  "id": "42",
  "age": 200
}
{
  "type": "object",
  "properties": {
    "id": { "type": "integer" },
    "email": { "type": "string", "format": "email" },
    "age": { "type": "integer", "maximum": 150 }
  },
  "required": ["id", "email"]
}

Three errors: /id is a string not integer, /email is missing, /age (200) exceeds maximum 150. Each error reports the exact JSON Pointer path so you can fix the data — or relax the schema — without guessing.

Discriminated Union — oneOf with const

{
  "type": "order.created",
  "data": { "orderId": "ORD-001234", "totalUsd": 49.99 }
}
{
  "oneOf": [
    {
      "properties": {
        "type": { "const": "order.created" },
        "data": {
          "type": "object",
          "properties": {
            "orderId": { "type": "string", "pattern": "^ORD-[0-9]{6}$" },
            "totalUsd": { "type": "number", "minimum": 0 }
          },
          "required": ["orderId", "totalUsd"]
        }
      },
      "required": ["type", "data"]
    },
    {
      "properties": {
        "type": { "const": "order.refunded" },
        "data": { "type": "object", "required": ["refundId"] }
      },
      "required": ["type", "data"]
    }
  ]
}

Webhook envelope validation. The first oneOf branch matches because type is "order.created". Switch type to "order.refunded" or break the orderId pattern to see how oneOf reports per-branch failures.

Array of Objects — items + uniqueItems

[
  { "sku": "A1", "qty": 3 },
  { "sku": "B2", "qty": 5 },
  { "sku": "A1", "qty": 3 }
]
{
  "type": "array",
  "minItems": 1,
  "uniqueItems": true,
  "items": {
    "type": "object",
    "properties": {
      "sku": { "type": "string", "pattern": "^[A-Z][0-9]+$" },
      "qty": { "type": "integer", "minimum": 1 }
    },
    "required": ["sku", "qty"]
  }
}

Two items are byte-identical, so uniqueItems triggers. Items 0 and 2 collide — the validator reports the duplicate at the array root. Useful for catching cart-line duplicates and merge-bug shipping requests.

How to Use

  1. 1

    Paste your JSON Schema

    Drop your schema into the right panel. The validator auto-detects the draft from the $schema URI if present; otherwise pick Draft 2020-12, 2019-09, or Draft-07 from the toolbar.

  2. 2

    Paste your JSON data

    Drop the JSON document you want to check into the left panel. Validation runs as you type; large inputs (>200 KB) switch to a manual Validate button to keep typing snappy.

  3. 3

    Read the error list

    Each error has a JSON Pointer path, a keyword, and a one-line message. Click an error to jump to the location in your data, fix it, and watch the count drop in real time.

Common JSON Schema Pitfalls

Type: integer vs number

JSON Schema treats 1.0 as a number but not an integer. If your contract says integer, the validator rejects 1.0 — even though most languages call it equal to 1. Pick number unless you genuinely need integer.

✗ Wrong
{ "qty": 1.0 }   schema: { "type": "integer" }   → error: not an integer
✓ Correct
{ "qty": 1 }     schema: { "type": "integer" }   → valid

Required at Wrong Nesting Level

required must sit next to properties, not inside one. A required array inside a property declaration is silently ignored — the validator never enforces it.

✗ Wrong
{ "properties": { "name": { "type": "string", "required": true } } }
✓ Correct
{ "properties": { "name": { "type": "string" } }, "required": ["name"] }

additionalProperties Default Is True

Without additionalProperties: false the schema is open — any extra key passes. Forgetting this is the most common reason schemas "accept everything."

✗ Wrong
{ "properties": { "id": { "type": "integer" } } }   accepts: { "id": 1, "foo": "bar", "x": null }
✓ Correct
{ "properties": { "id": { "type": "integer" } }, "additionalProperties": false }

OpenAPI 3.0 nullable vs Draft 2020-12 Type Array

OpenAPI 3.0 uses nullable: true; Draft 2020-12 uses type: ["string", "null"]. Mixing them produces schemas that look right but never actually allow null.

✗ Wrong
{ "type": "string", "nullable": true }   in 2020-12: nullable is just an unknown keyword
✓ Correct
{ "type": ["string", "null"] }   in 2020-12: explicitly allows null

Pattern Without Anchors

JSON Schema regex matches anywhere by default — pattern: "^[A-Z]+$" anchors to the whole string, but pattern: "[A-Z]+" matches if any uppercase letter exists anywhere.

✗ Wrong
pattern: "[A-Z]+"   accepts: "helloX"   (because X matches)
✓ Correct
pattern: "^[A-Z]+$"   accepts only: "HELLO"

oneOf Where anyOf Was Meant

oneOf requires exactly one branch to match. If two branches accept the same shape, oneOf fails on data that anyOf would pass — and the error message is confusing ("matches more than one").

✗ Wrong
oneOf: [ { type: "string" }, { type: "string", maxLength: 10 } ]   on: "hi"   → error: matches both
✓ Correct
anyOf: [ { type: "string" }, { type: "string", maxLength: 10 } ]   on: "hi"   → valid

Common Use Cases

API Request Validation
Paste a request body and your endpoint's schema before deploying. Catch 400 responses your tests didn't cover — missing required fields, wrong types, out-of-range numbers.
Webhook Payload Verification
Vendor sent a payload your handler rejects? Validate the actual payload against your schema, then against the vendor's published schema. The diff between the two is your bug.
Config File Linting
package.json, tsconfig.json, helm values.yaml — every config file has a public schema. Paste the schema, paste the config, find the typo. Skip the trial-and-error.
OpenAPI Component Testing
Lift a schema component from an OpenAPI 3.1 document, paste it here, validate sample payloads. Faster than spinning up a mock server, deterministic, no SDK needed.
Form-Submission Pre-Flight
Paste a sample form payload before wiring frontend validation. Confirm the schema rejects what you expect, accepts what you expect, then ship the same schema to client and server.
Data-Pipeline Contract Check
ETL output drifted? Paste a sample row and the downstream schema. Pinpoint which producer changed and which keys broke before the pipeline retries 10,000 records.

Technical Details

Draft 2020-12 Compliant
Implements the published Draft 2020-12 spec — keywords, type system, format vocabulary. Cross-checked against Ajv 8.x and ajv-formats output.
JSON Pointer Error Paths
Errors use RFC 6901 JSON Pointer (/user/email/0). Every keyword failure points to a single resolvable location in the data — no ambiguity, no string-search.
Internal $ref Resolution
Resolves $ref pointers within a single document (#/$defs/foo, #/properties/bar). Cycles detected and reported. External HTTP $refs disabled for privacy.

Best Practices

Always Set additionalProperties: false
On input contracts (request bodies, config files, queue messages), unknown keys are usually bugs — typos, accidental fields, or attacker probing. Reject them by default.
Use $defs for Reusable Subschemas
Inline the same shape twice and they drift. Move shared definitions to $defs and reference with $ref — one source of truth, every change applies everywhere.
Validate Before Business Logic
Run schema validation right after JSON.parse, before touching the parsed structure. Type narrowing, defaulting, and persistence all assume the contract holds — make sure it does.

Frequently Asked Questions

What is JSON Schema validation?
JSON Schema validation checks whether a JSON document matches a contract written in JSON Schema syntax. The schema declares field types, required keys, allowed values, and structural rules; the validator walks both documents in parallel and reports any path that violates the contract. It runs at the boundary between untrusted input (API request, webhook, config file, form payload) and your business logic — catching shape errors before they corrupt downstream code. See our complete guide to JSON Schema validation for end-to-end Node, Python, and browser examples.
Which JSON Schema drafts does this validator support?
Draft 2020-12 (default and recommended), Draft 2019-09, and Draft-07. The validator auto-detects the draft from the schema's $schema URI when present and falls back to your selection from the dropdown otherwise. For new projects in 2026 use Draft 2020-12 — it is what OpenAPI 3.1 uses natively and what Ajv defaults to. Draft-07 remains common in legacy codebases (older AJV setups, Helm charts, VS Code settings).
How do I validate JSON against a schema?
Paste your JSON data into the left panel and your JSON Schema into the right panel. The validator runs instantly as you type — green check means valid, red list means errors. Each error includes a JSON Pointer path (for example /user/email), the failing keyword (type, required, pattern, minimum), and a human-readable message. Click any error to jump to the offending line. No upload, no signup.
What's the difference between JSON Schema validation and JSON syntax validation?
JSON syntax validation only confirms the document parses — no extra commas, no missing braces. JSON Formatter handles that. JSON Schema validation runs after parsing and checks whether the parsed structure matches the contract: required fields present, types correct, values within range. You typically run both — format first to confirm parseable, then validate against the schema.
Why is my schema rejecting JSON that looks correct?
Five usual suspects: (1) additionalProperties: false — your data has a key the schema didn't declare, often a typo or a new field; (2) type: "integer" vs "number" — JSON Schema treats 1.0 as a number, not an integer; (3) format keywords (email, uri, uuid) reject malformed strings even when they look fine; (4) required at the wrong nesting level — required must appear next to properties, not inside one; (5) the JSON has a string "42" where the schema expects integer 42. The error path will pinpoint which one.
Does this support $ref and remote schema references?
Internal $ref pointers (#/$defs/foo, #/properties/bar) work out of the box. Remote $ref to external URLs is intentionally disabled — fetching external schemas would leak your validation activity to third parties and break the privacy model. To validate against a multi-file schema, inline the referenced definitions into a single document using $defs, or run validation in your own CI with Ajv where remote refs are appropriate.
What does additionalProperties: false do?
additionalProperties: false rejects any key that isn't declared in properties. It's the single most useful keyword for tightening contracts — without it, schemas are open by default and silently accept misspelled or malicious fields. Always set additionalProperties: false on input contracts (request bodies, config files, queue messages). Leave it true (or omit it) only when the schema is a partial description of a larger document.
How do I validate JSON against a schema in Node.js or Python?
Node: install Ajv (npm i ajv ajv-formats), call new Ajv().compile(schema), then validate(data). Python: install jsonschema (pip install jsonschema), call jsonschema.validate(data, schema). For TypeScript, generate types from the schema using json-schema-to-typescript so compile-time and runtime stay in sync. Our JSON Schema validation guide has copy-paste recipes for Node, Python, and browser.
What's the difference between oneOf, anyOf, and allOf?
allOf — must match every subschema (intersection, used for composition). anyOf — must match at least one (union, fast-fail). oneOf — must match exactly one (discriminated union, slower but stricter). Use oneOf for discriminated unions like webhook events tagged by type; use anyOf for permissive unions; use allOf to extend a base schema with extra constraints. oneOf is the slowest because it tests every branch — prefer anyOf when exactly-one isn't required.
Does it support OpenAPI schemas?
OpenAPI 3.1 uses Draft 2020-12 natively, so any OpenAPI 3.1 schema component pastes in directly. OpenAPI 3.0 uses a Draft 4 subset that's mostly compatible — you may hit edge cases around nullable: true (3.0 syntax) which Draft 2020-12 expresses as type: ["string", "null"]. For full OpenAPI document validation (paths, operations, security), use a dedicated OpenAPI linter like Spectral; this tool focuses on the schema portion.
Why does the validator say my JSON Schema is itself invalid?
JSON Schema is a JSON document that must be valid JSON before it can be a valid schema. Common causes: trailing comma in a properties object, single quotes instead of double, $schema set to a non-existent draft URL, or required listed as a string instead of an array. Format the schema in JSON Formatter first to surface syntax issues, then paste it back here for semantic validation.
Does the tool send my JSON or schema to a server?
No. All parsing and validation runs locally in your browser. Your JSON, your schema, and the validation results never leave your machine — no upload, no localStorage of inputs, no analytics on what you paste. Safe for proprietary API contracts, internal config files, and sensitive payloads. Only your draft selection persists in localStorage so it survives a refresh; clear browser data to wipe it.
Can I validate JSON Lines (NDJSON) or multiple documents?
This tool validates one document per run. For JSON Lines, validate each line individually or use Ajv in Node with a schema and a stream parser like JSONStream. For batch validation of large datasets, prefer the command-line — ajv-cli or check-jsonschema (Python) handle thousands of files per second with a single schema compile.

Related Tools

View all tools →