Schema Validator

Validate JSON-LD markup against Schema.org and Google’s structured-data expectations. Paste your markup, get a pass / warn / error report, entirely in your browser.

This validator checks something the others do not: whether two nodes on the same page claim the same @id. When that happens one of them is discarded silently, and the usual symptom is structured data that validates cleanly everywhere else and still produces no rich result.

Paste a JSON-LD block, or paste an entire page of HTML. Pasting the page is the point: an @id collision usually happens between two separate ld+json blocks, one written by an SEO plugin and one written by hand, so checking either block on its own shows nothing wrong.

Everything runs in your browser. Nothing is uploaded, stored or logged.

Live v1.0 · Updated April 2026 Free · No login
Validator Idle
Paste a JSON-LD block, or paste a whole page of HTML and every block in it is checked together. Runs locally, nothing is uploaded.
Runs locally · nothing sent to a server

How it works

Paste a block of JSON-LD and the validator parses it, walks every node (including @graph arrays), and checks each one against the required and recommended properties for its @type.

Every result is graded on three levels:

  • Error, a required property is missing or malformed. Google is unlikely to treat the block as a valid rich result.
  • Warning, a recommended property is missing. The markup is valid but leaves rich-result coverage on the table.
  • Pass, the property is present and non-empty.

It covers Article, Product, FAQPage, BreadcrumbList, Organization, Person, WebSite, and LocalBusiness, with deeper checks on nested shapes like FAQ questions, breadcrumb items, publisher logos, and product offers. Nothing you paste leaves your machine.

What this validator checks

Eight classes of fault, each of which produces markup that looks correct and does not work.

Duplicate @id across nodes

Two nodes claiming the same @id is the most common cause of schema that validates but never produces a rich result. The parser treats @id as the identity of a node, so the second definition replaces the first rather than adding to it. Nothing warns you. This is near-universal on WordPress sites where an SEO plugin emits a BreadcrumbList and a theme or a block emits another.

Unresolved @id references

A bare {"@id": "..."} is a pointer to a node defined elsewhere in the graph, not a node itself. If nothing defines that @id, the reference resolves to nothing and whatever depended on it is dropped. This is what usually breaks a publisher or breadcrumb that looks correct in the source.

Dates that are not ISO 8601

datePublished, dateModified, startDate and their relatives must be ISO 8601: 2026-08-22 or 2026-08-22T09:00:00+00:00. A human-readable date like 22 August 2026 is not parsed, and the property is ignored rather than flagged.

Relative URLs where absolute is required

url, image, logo and sameAs are not resolved against the page they appear on. A path like /img/cover.png is discarded. Every one of them needs the full https:// address.

Missing required properties, by type

Each type has properties without which no rich result is possible: headline on an Article, name and address on a LocalBusiness, price and priceCurrency on an Offer. Recommended properties are reported separately, because their absence costs eligibility for some features rather than all of them.

Incomplete FAQ entries

A FAQPage needs every question to carry a name and an acceptedAnswer containing text. One malformed question invalidates the whole block, so a page with nine good questions and one empty answer gets nothing.

Breadcrumb positions out of sequence

itemListElement entries need a position starting at 1 and incrementing by one. Gaps and duplicates are the usual result of generating breadcrumbs in a loop that skips a level.

Malformed JSON

A trailing comma, a smart quote pasted from a document, or an unescaped newline inside a string. The block is discarded entirely, so a single stray character costs every node in it.

Error reference

Every error this tool reports, and what to do about it.

MessageWhat to do
Two nodes share the same @idOne of them is being discarded. Decide which node owns that identifier and give the other a fragment nothing else claims. If an SEO plugin owns #breadcrumb, #webpage, #website, #organization or #person on your site, do not reuse those.
Reference to X but no node defines itEither define the node that @id points at, or replace the reference with the object inline.
datePublished is not ISO 8601Reformat to YYYY-MM-DD, optionally with a time and offset.
image is not an absolute URLPrefix with your full origin, including https://.
required headline missingAdd it. Without a required property the type cannot produce a rich result at all, regardless of what else is present.
FAQPage: N question(s) incompleteFind the entries missing name or acceptedAnswer.text. One bad entry invalidates the block.
BreadcrumbList: positions are not 1..n in orderRenumber position from 1 with no gaps.
Block N is not valid JSONUsually a trailing comma or a curly quote. Paste through a plain-text editor first if the markup came from a document.

Related reading

Frequently asked

The most common cause is two nodes sharing an @id. The parser treats @id as identity, so the second definition replaces the first and one node is silently discarded. Validators that check a single block in isolation cannot see it, because both blocks are individually valid. Paste the whole page here and the collision is reported directly.

Yoast claims specific @id fragments on every page, including #breadcrumb, #webpage, #website, #organization and #person. If you hand-write a node using one of those fragments, whichever loads second wins. Pick a fragment no plugin uses, or let the plugin own that node entirely.

Yes, and for collision detection you have to. Paste the page source and every application/ld+json block is extracted and checked together, which is the only way an @id shared between two blocks becomes visible.

No. The validator runs entirely in your browser. Nothing is uploaded, stored or logged, which also means it works on staging sites and behind a login where a URL-based validator cannot reach.

Required properties are those without which the type cannot produce a rich result at all. Recommended properties affect which features you qualify for and how the result is presented. This validator reports them separately so you can tell a blocker from an improvement.

Check three things in order. Every question needs a name and an acceptedAnswer with text, and one malformed entry invalidates the whole block. The questions and answers must be visible on the page, not hidden behind a tab or only present in the markup. And FAQ rich results are now limited to authoritative government and health sites for most queries, so valid markup does not guarantee display.

No, and it is not trying to. Google’s tool tells you what Google will render, which is the final word on eligibility. This one finds structural faults the Rich Results Test does not surface, particularly collisions across blocks, and it works on markup that is not published yet.

ISO 8601. 2026-08-22 for a date, or 2026-08-22T09:00:00+00:00 with a time and offset. Anything else is ignored rather than reported as an error, which is why a wrong date format so often looks like a missing property.

Almost always because it is a relative path. image, url, logo and sameAs are not resolved against the current page, so /img/cover.png is discarded. Use the full address.

The main ones are Article, Product, Offer, FAQPage, HowTo, Recipe, Event, JobPosting, Course, VideoObject, SoftwareApplication, BreadcrumbList, Organization, LocalBusiness, WebSite, Review and AggregateRating. Types like WebPage and Person are valid and useful for describing your graph, but do not produce a result of their own.