How to Extract JSON-LD and Schema Markup from Websites for SEO Audits
Technical SEOJSON-LDSchema MarkupWeb ScrapingData Extraction

How to Extract JSON-LD and Schema Markup from Websites for SEO Audits

SScraper Studio Editorial Team
2026-11-07
6 min read

Learn how to extract JSON-LD, Microdata, and RDFa, normalize nested schema records, and build a repeatable structured-data SEO audit.

Extracting structured data from a website gives an SEO audit a machine-readable view of the page’s intended entities, properties, and relationships. This guide provides a repeatable checklist for finding JSON-LD, Microdata, and RDFa, parsing nested records, handling multiple schemas, and exporting validation-ready data for comparison across templates or crawls.

Overview

Structured data can appear in several formats, and a single page may contain more than one item or vocabulary. The three formats most commonly encountered during a schema markup audit are:

  • JSON-LD: Data is placed in a <script type="application/ld+json"> element, usually in the document head or body. It is often the simplest format to extract because the contents can be parsed as JSON.
  • Microdata: Schema properties are attached to HTML elements through attributes such as itemscope, itemtype, and itemprop.
  • RDFa: Semantic attributes such as typeof, property, and vocab are added to ordinary HTML elements.

Your extraction workflow should preserve the source URL, retrieval time, markup format, schema type, raw record, and parsing status. Keeping the raw markup alongside normalized fields makes the audit easier to troubleshoot when a template changes.

For a small number of static pages, browser developer tools and a short script may be sufficient. For a sitewide audit, use a crawler that records response status, canonical URL, rendered HTML when necessary, and all structured-data blocks. If the page builds its markup with JavaScript, a browser-based workflow may be required. The practical difference between downloading HTML and rendering a page is covered in this guide to Playwright web scraping.

Checklist by scenario

Scenario 1: Inspect one page manually

  1. Open the page source, not only the rendered DOM, and search for application/ld+json, itemscope, itemprop, typeof, and property.
  2. Record every structured-data block. Do not stop after finding the first script, because pages commonly contain separate records for different entities.
  3. Copy the original block before editing or formatting it. The original is useful when a parser reports invalid JSON or an unexpected value type.
  4. Identify the top-level type and the relationships between nested objects, such as an article, its author, and its publisher.
  5. Compare the extracted fields with the visible page content. A record that describes content not present on the page deserves review rather than automatic acceptance.

Scenario 2: Extract JSON-LD with a script

A basic Python workflow can collect JSON-LD from downloaded HTML. The example below deliberately keeps both parsed objects and parsing errors so that a failed record is not silently discarded.

from bs4 import BeautifulSoup
import json

html = open("page.html", encoding="utf-8").read()
soup = BeautifulSoup(html, "html.parser")
records = []

for block in soup.select('script[type="application/ld+json"]'):
    raw = block.string or block.get_text()
    try:
        records.append({"status": "parsed", "data": json.loads(raw)})
    except json.JSONDecodeError as error:
        records.append({
            "status": "error",
            "error": str(error),
            "raw": raw
        })

print(json.dumps(records, indent=2, ensure_ascii=False))

This is useful for a controlled sample or a static crawl. For production extraction, also store the URL, HTTP status, content type, response time if relevant to your pipeline, and whether the document was rendered. A broader comparison of extraction approaches is available in Web Scraping APIs vs HTML Scraping.

Scenario 3: Handle arrays and nested objects

JSON-LD is not always one object. The top level may be an array, an object containing an @graph array, or a single entity. Normalize these shapes before exporting rows:

  • If the top level is an array, inspect each member independently.
  • If @graph is present, treat each graph member as a candidate record.
  • Preserve @id values so relationships can be traced across records.
  • Keep nested objects such as authors, images, offers, and publishers as structured JSON until you decide which fields belong in separate columns.
  • Do not assume every property is a string. Values may be arrays, numbers, booleans, URLs, or objects.

Scenario 4: Audit Microdata and RDFa

For Microdata, start at each element with itemscope and capture its itemtype. Then collect descendant elements with itemprop, taking the value from the appropriate attribute when one exists: for example, content for a meta element, href for a link, or src for an image. RDFa requires similar care with typeof and property, while also preserving the element’s relevant URL or text value.

These formats are easier to misread with a flat CSS selector because nested items can belong to a parent entity or to a related entity. Build a tree or retain each element’s ancestry when the audit needs relationship-level accuracy.

Scenario 5: Export audit-ready records

A useful CSV might include:

FieldPurpose
URLIdentifies the audited page.
Markup formatDistinguishes JSON-LD, Microdata, and RDFa.
Schema typeRecords the declared entity type.
Entity IDPreserves an @id or equivalent identifier.
Key propertiesStores selected normalized fields for review.
Raw markupSupports debugging and later reprocessing.
Parse statusSeparates valid, incomplete, and failed records.

For a JSON export, use a structure such as {"url":"https://example.com/page","format":"json-ld","type":"Article","status":"parsed","raw":{},"normalized":{}}. Keep normalized fields deliberately narrow; the raw object should remain the source of truth.

What to double-check

  • Rendered versus source HTML: Run a comparison when a page uses client-side rendering or changes markup after load.
  • Multiple entities: Confirm whether several records describe separate entities, connected entities, or duplicate declarations.
  • Type consistency: Check that the declared type, nested properties, and page template describe the same subject.
  • URLs and identifiers: Normalize URL encoding carefully, retain fragments when they identify an entity, and avoid replacing IDs with guessed values.
  • Value provenance: Record whether a value came from JSON-LD, an HTML attribute, visible text, or a rendered DOM. This helps explain discrepancies.
  • Validation context: A parser can confirm that data is syntactically readable; it does not by itself determine whether the implementation is complete, appropriate, or eligible for a particular search feature. Review the relevant Schema.org vocabulary and current search documentation separately.

For recurring technical SEO scraping, add a change-detection step. Compare the current normalized output with the previous crawl, then link each change to a template, migration, content update, or parser change where possible. The workflow in Technical SEO Scraping provides a useful model for organizing this type of audit.

Common mistakes

  1. Using a regular expression as the JSON parser: Regex can help locate script tags, but nested JSON should be parsed with a JSON library.
  2. Keeping only the first record: This loses connected entities and can make a page appear incomplete.
  3. Flattening too early: Converting nested authors, images, or offers into text before preserving the original structure makes later analysis harder.
  4. Ignoring malformed blocks: Store the error and raw value so the development team can reproduce the issue.
  5. Auditing only rendered output: A browser view may contain generated elements that are not present in the initial response. Capture both views when the distinction matters.
  6. Confusing extraction with validation: Extraction answers what markup exists. Validation and SEO review answer whether it is correctly modeled and appropriate for the page.
  7. Failing to identify the crawler: Save the tool version, rendering mode, and extraction rules. Otherwise, a future difference may be impossible to explain.

When to revisit

Revisit this workflow before seasonal planning cycles, after a site migration, when a CMS or frontend framework changes, and whenever templates are redesigned. It is also worth rerunning after changing your crawler, parser, rendering settings, or export schema. A parser update can change results even when the website has not changed.

For a practical recurring process, begin with a representative sample of page types, then expand to a full crawl after the extraction rules are stable:

  1. Define the page templates and schema types you expect to find.
  2. Crawl a sample in both source and rendered modes where needed.
  3. Extract every structured-data block and retain the raw input.
  4. Normalize only the fields needed for comparison and reporting.
  5. Review parse failures, duplicates, missing relationships, and unexpected types.
  6. Export a validation-ready dataset and record the crawl configuration.
  7. Schedule the next review around the next template, workflow, or documentation change.

That checklist turns structured data extraction from a one-off inspection into a maintainable SEO data pipeline. When the site or tooling changes, update the assumptions, rerun the sample, and only then rely on the results of the larger audit.

Related Topics

#Technical SEO#JSON-LD#Schema Markup#Web Scraping#Data Extraction
S

Scraper Studio Editorial Team

Technical SEO and Data Extraction Editor

Senior editor and content strategist. Writing about technology, design, and the future of digital media. Follow along for deep dives into the industry's moving parts.