Skip to content

Repository files navigation

schemacraft-validator

schemacraft-validator

Schema.org structured data validator — accuracy-matched to validator.schema.org

npm versionCIdownloadslicensestarsTypeScriptcoverageaccuracynode

InstallationQuick StartCLIServerAPIAccuracyContributing


Why schemacraft-validator?

The Schema Markup Validator (formerly Google's Structured Data Testing Tool) is the industry standard for validating Schema.org markup. SEOs, developers, and tools reference its output as ground truth.

schemacraft-validator brings that same validation to your codebase — as a library, CLI tool, or self-hostable server. No more manual copy-pasting into a web form.

  • Accuracy-matched — tested against the real validator with real-world schemas; error counts match exactly
  • All 3 formats — JSON-LD, Microdata, and RDFa extraction from HTML
  • Raw JSON-LD support — paste the same JSON-LD you'd use on validator.schema.org
  • Full Schema.org vocabulary — 1003 types, 1676 properties, complete type hierarchy with inheritance
  • @id cross-references — resolves {"@id": "..."} within @graph structures
  • SDTT-compatible heuristics — text-for-entity tolerance, URL coercion, string-to-number/boolean
  • Three interfaces — Library API, CLI, and Express server

Installation

npm install schemacraft-validator

Optional: For JavaScript rendering support (SPAs, dynamically injected JSON-LD):

npm install puppeteer

Quick Start

Library

import{validate,validateMarkup,validateJsonLd}from'schemacraft-validator';// Validate a URLconstresult=awaitvalidate('https://example.com');// Validate raw HTMLconstresult=validateMarkup(` <html><head> <script type="application/ld+json"> {"@context":"https://schema.org","@type":"Product","name":"Widget"} </script> </head><body></body></html>`);// Validate raw JSON-LD (string or object) — no HTML neededconstresult=validateJsonLd({"@context": "https://schema.org","@type": "Product","name": "Widget Pro","offers": {"@type": "Offer","price": "29.99","priceCurrency": "USD"}});console.log(result.isValid);// trueconsole.log(result.summary.types);// ["Product"]console.log(result.errors);// []console.log(result.warnings);// []

Batch Validation

import{validateBatch}from'schemacraft-validator';constresults=awaitvalidateBatch(['https://example.com/page1','https://example.com/page2','https://example.com/page3',]);for(constresultofresults){console.log(`${result.url}: ${result.isValid ? 'VALID' : 'INVALID'}`);}

CLI

# Validate a URL
npx schemacraft-validator check https://example.com
# Validate a local HTML file
npx schemacraft-validator check ./page.html
# Validate raw JSON-LD (no HTML wrapper needed)
npx schemacraft-validator check-json ./schema.json
# JSON output (for piping / scripting)
npx schemacraft-validator check https://example.com --format json
# With JavaScript rendering (requires puppeteer)
npx schemacraft-validator check https://spa-example.com --render-js
# Custom timeout
npx schemacraft-validator check https://slow-site.com --timeout 30000

CLI Output Example

Schema Validation Report
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
URL: https://example.com
Status: ✅ Valid (0 errors, 0 warnings)
Entities: 2 found (json-ld)
─── Product ──────────────────────────────────────────
name "Widget Pro"
description "The best widget ever made"
offers → Offer
price "29.99"
priceCurrency "USD"
─── Organization ─────────────────────────────────────
name "Example Corp"
url "https://example.com"

Exit Codes

CodeMeaning
0Valid — zero errors
1Invalid — has errors
2Runtime error (fetch failed, file not found, etc.)

Server

Start a self-hostable validation server:

# Start on port 3001
npx schemacraft-validator serve --port 3001
# With secret-based auth (for sidecar deployments)
npx schemacraft-validator serve --port 3001 --secret my-secret-key

Endpoints

POST /validate

# Validate a URL
curl -X POST http://localhost:3001/validate \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}'# Validate raw HTML
curl -X POST http://localhost:3001/validate \
-H "Content-Type: application/json" \
-d '{"markup": "<html>...</html>"}'# Validate raw JSON-LD
curl -X POST http://localhost:3001/validate \
-H "Content-Type: application/json" \
-d '{"jsonld": {"@context":"https://schema.org","@type":"Product","name":"Test"}}'

POST /validate/batch

curl -X POST http://localhost:3001/validate/batch \
-H "Content-Type: application/json" \
-d '{"urls": ["https://example.com/a", "https://example.com/b"]}'

Max 100 URLs per batch request.

GET /health

curl http://localhost:3001/health
# {"status":"ok","version":"1.0.0","uptime":12345}

API Reference

Functions

FunctionInputReturnsDescription
validate(url, options?)URL stringPromise<ValidationResult>Fetch URL and validate
validateMarkup(html, options?)HTML stringValidationResultValidate raw HTML
validateJsonLd(input, options?)JSON string or objectValidationResultValidate raw JSON-LD
validateBatch(urls, options?)URL arrayPromise<ValidationResult[]>Validate multiple URLs

Options

interfaceValidateOptions{formats?: ('json-ld'|'microdata'|'rdfa')[];// Default: all threefollowRedirects?: boolean;// Default: truerenderJavascript?: boolean;// Default: false (needs puppeteer)timeout?: number;// Default: 10000msincludeRaw?: boolean;// Default: falseheaders?: Record<string,string>;// Custom HTTP headersproxy?: string;// HTTP proxy URLuserAgent?: string;// Default: "SchemaCraftValidator/x.x.x"}

ValidationResult

interfaceValidationResult{url?: string;// URL validated (undefined for markup/jsonld input)timestamp: string;// ISO 8601 timestampduration: number;// Processing time in msisValid: boolean;// true if zero errors (warnings don't count)entities: ValidatedEntity[];// Detected Schema.org entitieserrors: ValidationIssue[];// All errorswarnings: ValidationIssue[];// All warningssummary: {totalEntities: number;totalTriples: number;types: string[];// e.g., ["Product", "Organization"]formats: ('json-ld'|'microdata'|'rdfa')[];errorCount: number;warningCount: number;};}

Issue Codes

CodeSeverityDescription
UNKNOWN_TYPEerror@type is not a recognized Schema.org type
UNKNOWN_PROPERTYerrorProperty not valid for this type (matches SDTT INVALID_PREDICATE)
INVALID_VALUE_TYPEerrorNested entity type doesn't match expected range (matches SDTT INVALID_OBJECT)
MALFORMED_JSONLDerrorInvalid JSON in script block
MISSING_TYPEerrorMissing @type on entity
FETCH_ERRORerrorHTTP fetch failed
DEPRECATED_TYPEwarningType is deprecated in Schema.org
DEPRECATED_PROPERTYwarningProperty is deprecated
EMPTY_VALUEwarningProperty value is empty string

For the full API reference, see docs/API.md.

Accuracy

How We Test

Every release is tested against validator.schema.org to ensure our output matches. We maintain:

  • 22 accuracy fixtures covering JSON-LD, Microdata, RDFa, @graph, @id references, nested entities, mixed formats, edge cases
  • Real-world validation against production schemas (e.g., ProxyScrape with 19 entities and @id cross-references — matched SDTT's 5 errors / 0 warnings exactly)
  • Weekly automated accuracy checks via GitHub Actions

Current Accuracy

MetricValue
Fixture accuracy100% (22/22)
Test coverage88.77%
Total tests203

What We Check (same as validator.schema.org)

  • Is @type a recognized Schema.org type?
  • Is each property valid for that type (including inherited from parent types)?
  • Does each property value match the expected type range?
  • @id cross-references resolved within @graph
  • Text-for-entity heuristic (tolerated, per SDTT behavior)
  • Multiple types, nested entities, deprecated types/properties

Known Divergences

We track every known difference in DIVERGENCES.md. Current divergences:

#BehaviorStatus
1JS rendering requires --render-js flagBy design
2Entity grouping differs from SDTT displayBy design

Supported Formats

FormatExtractionValidationNotes
JSON-LD<script type="application/ld+json">Full@graph, @id refs, multiple blocks, BOM handling
Microdataitemscope/itemtype/itempropFullNested entities, link/img/meta values
RDFatypeof/property/vocabFullQuad grouping, nested entities
Raw JSON-LDDirect input (no HTML)FullSame as pasting into validator.schema.org

Schema.org Vocabulary

The validator ships with a vendored copy of the Schema.org vocabulary containing:

  • 1003 types with full class hierarchy
  • 1676 properties with domain/range definitions
  • Transitive subtype checking (e.g., LocalBusiness is valid where Organization or Place is expected)
  • Property inheritance (e.g., Product inherits all Thing properties)

The vocabulary is updated automatically via a weekly GitHub Action that checks for new Schema.org releases.

Use Cases

  • SEO auditing — validate Schema.org markup before deploying pages
  • CI/CD pipelines — add schema validation to your build process
  • Content management — validate markup generated by CMS plugins
  • API services — self-host a validation endpoint for your platform
  • Development — catch schema errors during development, not after indexing

Docker

Quick Start

# Build and run
docker compose up -d
# Test it
curl http://localhost:3001/health
curl -X POST http://localhost:3001/validate \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}'

Configuration

Env VariableCLI FlagDefaultDescription
BEARER_TOKEN--bearer-token(none)Require Authorization: Bearer <token> for API access
--allowed-origins*CORS allowed origins (comma-separated)

With Auth

# Via env
BEARER_TOKEN=my-secret-token docker compose up -d
# Call with auth
curl -X POST http://localhost:3001/validate \
-H "Content-Type: application/json" \
-H "Authorization: Bearer my-secret-token" \
-d '{"url": "https://nhaphonet.vn"}'

Restrict CORS

# docker-compose.ymlservices:
schema-test:
# ...command: serve --port 3001 --allowed-origins "https://app1.com,https://app2.com"

Verify

# Check the server is running
curl http://localhost:3001/health
# Validate a URL
curl -X POST http://localhost:3001/validate -H "Content-Type: application/json" -d '{"url": "https://example.com"}'# Validate raw JSON-LD
curl -X POST http://localhost:3001/validate -H "Content-Type: application/json" -d '{"jsonld": {"@context":"https://schema.org","@type":"Product","name":"Test"}}'# Batch validation
curl -X POST http://localhost:3001/validate/batch -H "Content-Type: application/json" -d '{"urls": ["https://site1.com", "https://site2.com"]}'

Requirements

  • Node.js >= 18
  • puppeteer (optional) — only needed for --render-js JavaScript rendering

Attribution

This project is a fork of Google's Schemarama, originally licensed under the Apache License 2.0.

Schema.org vocabulary data is provided by Schema.org under the CC BY-SA 3.0 license.

This project is not affiliated with, endorsed by, or sponsored by Google or Schema.org.

Contributing

We welcome contributions! See CONTRIBUTING.md for guidelines.

git clone https://github.com/Elbradey8/schemacraft-validator.git
cd schemacraft-validator
npm install
npm test# 203 tests
npm run typecheck # TypeScript strict mode
npm run build # CJS + ESM + DTS

License

Apache License 2.0 — see NOTICE for attribution details.


Built by Abdullah Elbradeyschemacraft.net

About

Schema.org structured data validator — accuracy-matched to validator.schema.org. Supports JSON-LD, Microdata, and RDFa. Library, CLI, and self-hostable server.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages