Schema.org Structured Data Extractor: JSON-LD, OpenGraph avatar

Schema.org Structured Data Extractor: JSON-LD, OpenGraph

Pricing

from $0.85 / 1,000 page parseds

Go to Apify Store
Schema.org Structured Data Extractor: JSON-LD, OpenGraph

Schema.org Structured Data Extractor: JSON-LD, OpenGraph

Extract schema.org JSON-LD, microdata, RDFa, OpenGraph and Twitter Cards from any URL list, flattened to ready-to-use fields: name, price, rating, dates, ingredients, salary. Filter by Product, Event, Recipe, JobPosting. No login. MCP-ready for AI agents. Errors are free. $1 per 1,000 pages.

Pricing

from $0.85 / 1,000 page parseds

Rating

0.0

(0)

Developer

ABM

ABM

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Security

Limited permissions

Share

Schema.org Structured Data Extractor: JSON-LD, Microdata, RDFa, OpenGraph, Twitter Cards

$1 per 1,000 pages. Errors, blocked pages and pages without structured data are free.

Paste a list of URLs and get back the schema.org structured data of every page — JSON-LD, microdata, RDFa, OpenGraph and Twitter Cards — normalised to one format and flattened into ready-to-use columns: name, price, currency, availability, rating, review count, brand, SKU/GTIN, author, dates, location, address, ingredients, cooking times, salary, employment type and more.

Filter by schema.org type (Product, Event, Recipe, JobPosting, Article, LocalBusiness, Movie...) and get only the entities you need, nested ones included (a Product inside an ItemList, a Recipe inside a WebPage).

  • No browser, no API key, no login: one light HTTP request per page.
  • Every syntax in one pass, normalised to the same JSON-LD shape.
  • Flat fields for spreadsheets, plus the full objects for developers.
  • Markdown summary per page, ready for LLMs and RAG.
  • onlyNew mode for scheduled runs: you only get (and pay for) pages whose data changed.
  • MCP-ready for Claude, Cursor, ChatGPT and other AI agents.

How much does it cost?

Pay per result, no monthly rental: $0.001 per parsed page (page-parsed event).

PagesPrice
100$0.10
1,000$1.00
10,000$10.00
100,000$100.00

You only pay for pages that actually delivered structured data. These are free: invalid URLs, duplicates, 404s, unreachable or blocked websites, pages without structured data, pages without the requested schemaTypes, and unchanged pages in onlyNew mode. The run stops cleanly when your maximum charge is reached.

What data does it extract?

SyntaxWhat is read
JSON-LDEvery <script type="application/ld+json"> block, @graph expanded, tolerant to trailing commas, CDATA and HTML escaping
Microdataitemscope / itemtype / itemprop, nested items, content, href, src, datetime values
RDFa Litevocab / typeof / property / resource
OpenGraphog:*, article:*, product:*, music:*, video:*, book:*, profile:*, fb:*
Twitter Cardstwitter:*
Meta<title>, meta description, canonical URL, language

Flat fields (taken from the main entity of the page): primaryType, name, description, image, entityUrl, brand, sku, gtin, mpn, price, priceCurrency, lowPrice, highPrice, availability, itemCondition, ratingValue, bestRating, ratingCount, reviewCount, author, publisher, datePublished, dateModified, startDate, endDate, eventStatus, eventAttendanceMode, locationName, address, latitude, longitude, telephone, openingHours, organizer, performer, prepTime, cookTime, totalTime, recipeYield, recipeCategory, recipeCuisine, calories, recipeIngredients, recipeInstructions, hiringOrganization, datePosted, validThrough, employmentType, jobLocation, jobLocationType, salaryMin, salaryMax, salaryCurrency, salaryUnit, genre, duration, director, actors, contentRating, keywords, inLanguage.

Full data: mainEntity (cleaned object), mainEntityFlat (dot keys like offers.price), entities (every entity with its type, syntax, @id and data), openGraph, twitterCards, markdown.

Input

FieldDescription
urlsPage URLs (required). Bare domains are accepted.
schemaTypesOptional filter, e.g. ["Product"], ["Event"], ["Recipe", "HowTo"], ["JobPosting"]. Subtypes match too.
syntaxesjson-ld, microdata, rdfa, opengraph, twitter (all by default).
onlyNewOnly return pages that are new or changed since the last run.
maxEntitiesPerPageMax entities kept per page (default 50).
proxyFallbackRetry a page once through a datacenter proxy if the site refuses the server IP (default on).
maxConcurrency / requestTimeoutSecsSpeed and timeout settings.
{
"urls": [
"https://www.imdb.com/title/tt0111161/",
"https://www.allrecipes.com/recipe/16354/easy-meatloaf/"
],
"schemaTypes": ["Movie", "Recipe"]
}

Output

One dataset item per page (abridged):

{
"url": "https://www.allrecipes.com/recipe/16354/easy-meatloaf/",
"finalUrl": "https://www.allrecipes.com/recipe/16354/easy-meatloaf/",
"status": "ok",
"statusCode": 200,
"schemaTypes": ["Recipe", "NewsArticle"],
"matchedTypes": ["Recipe"],
"syntaxesFound": ["json-ld", "opengraph", "twitter"],
"entityCount": 1,
"primaryType": "Recipe",
"name": "Easy Meatloaf",
"image": "https://www.allrecipes.com/thmb/....jpg",
"author": "Janet Caldwell",
"datePublished": "1998-05-07T13:22:03.000-04:00",
"ratingValue": 4.6,
"ratingCount": 6820,
"prepTime": "PT10M",
"cookTime": "PT60M",
"totalTime": "PT70M",
"recipeYield": "8",
"calories": "372 kcal",
"recipeIngredients": ["1 ½ pounds ground beef", "1 egg", "1 onion, chopped", "..."],
"recipeInstructions": ["Preheat the oven to 350 degrees F (175 degrees C).", "..."],
"price": null,
"ogTitle": "Easy Meatloaf Recipe",
"twitterCard": "summary_large_image",
"mainEntity": { "@type": "Recipe", "name": "Easy Meatloaf", "aggregateRating": { "@type": "AggregateRating", "ratingValue": "4.6" } },
"mainEntityFlat": { "@type": "Recipe", "name": "Easy Meatloaf", "aggregateRating.ratingValue": "4.6" },
"entities": [{ "type": "Recipe", "types": ["Recipe"], "syntax": "json-ld", "id": null, "data": { "...": "..." } }],
"openGraph": { "og:title": "Easy Meatloaf Recipe", "og:type": "article" },
"twitterCards": { "twitter:card": "summary_large_image" },
"markdown": "# Easy Meatloaf\n\n- **Type:** Recipe\n- **Rating:** 4.6\n...",
"changedSinceLastRun": null,
"viaProxy": false,
"fetchedAt": "2026-10-23T08:00:00+00:00",
"error": null
}

Free rows explain what happened, with status set to noStructuredData, noMatchingType, blocked, notFound, notHtml, error or invalidInput and a human-readable error.

The Overview view gives a table (URL, type, name, price, rating, dates, image); the Entities view gives one row per schema.org entity.

Use cases

1. Price and stock monitoring for an e-commerce team

A pricing analyst follows 2,000 competitor product pages. Scheduled every morning with onlyNew, the run only returns (and charges) the products whose price, availability or rating changed, so a typical day costs a few cents instead of $2.

{ "urls": ["https://shop.example.com/p/espresso-machine-x200", "..."], "schemaTypes": ["Product"], "onlyNew": true }
[{ "name": "Espresso Machine X200", "brand": "Acme", "gtin": "4006381333931", "price": 249.9, "priceCurrency": "EUR", "availability": "InStock", "ratingValue": 4.4, "reviewCount": 312, "changedSinceLastRun": true }]

The dataset goes to Google Sheets through the Apify integration. A conditional format flags price drops, and a Slack alert fires when a product goes OutOfStock.

2. Recipe database for a food app

A product team builds a recipe catalogue for a meal-planning app from 10,000 recipe URLs found in sitemaps: $10 for the whole batch, with ingredients and steps already split into arrays.

{ "urls": ["https://www.allrecipes.com/recipe/16354/easy-meatloaf/", "..."], "schemaTypes": ["Recipe"] }
[{ "name": "Easy Meatloaf", "totalTime": "PT70M", "recipeYield": "8", "calories": "372 kcal", "recipeIngredients": ["1 ½ pounds ground beef", "..."], "recipeInstructions": ["Preheat the oven...", "..."], "ratingValue": 4.6 }]

Rows are loaded into Postgres. The markdown field is embedded as-is into a vector store, so the app's assistant can answer "what can I cook in 30 minutes with ground beef?".

3. Events aggregator for a city guide

An editor collects concerts, exhibitions and meetups from 300 venue and ticketing pages every week (about $0.30 per run). Event also matches MusicEvent, TheaterEvent, ExhibitionEvent...

{ "urls": ["https://venue.example.org/agenda", "..."], "schemaTypes": ["Event"] }
[{ "primaryType": "MusicEvent", "name": "Jazz Night", "startDate": "2026-11-14T20:30", "locationName": "Le Petit Club", "address": "12 rue X, 31000, Toulouse, FR", "price": 15, "priceCurrency": "EUR", "eventStatus": "EventScheduled" }]

A Make scenario publishes new rows to the guide's CMS and a weekly newsletter.

4. Job board enrichment for a recruiting startup

A recruiting startup pulls JobPosting markup from 5,000 company career pages: title, company, location, remote flag and salary range for $5.

{ "urls": ["https://careers.example.com/jobs/data-engineer-1234", "..."], "schemaTypes": ["JobPosting"] }
[{ "name": "Data Engineer", "hiringOrganization": "Example SA", "jobLocation": "Paris, FR", "jobLocationType": "TELECOMMUTE", "employmentType": "FULL_TIME", "salaryMin": 55000, "salaryMax": 70000, "salaryCurrency": "EUR", "salaryUnit": "YEAR", "datePosted": "2026-10-20" }]

5. SEO check of rich-result markup

An SEO consultant checks 500 key URLs of a client site after a redesign. schemaTypes and syntaxesFound show at a glance which templates lost their Product or Breadcrumb markup, and noStructuredData rows list the broken pages, for free.

API usage

Python

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("<USERNAME>/structured-data-extractor").call(run_input={
"urls": ["https://www.imdb.com/title/tt0111161/"],
"schemaTypes": ["Movie"],
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["name"], item["ratingValue"], item["genre"])

JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('<USERNAME>/structured-data-extractor').call({
urls: ['https://www.allrecipes.com/recipe/16354/easy-meatloaf/'],
schemaTypes: ['Recipe'],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0].recipeIngredients);

One HTTP call (run and get the results synchronously):

curl -X POST "https://api.apify.com/v2/acts/<USERNAME>~structured-data-extractor/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"urls":["https://www.imdb.com/title/tt0111161/"]}'

Integrations (Make, Zapier, n8n, Google Sheets)

  • n8n: Schedule Trigger (daily) → Apify node "Run actor" with {"urls": [...], "schemaTypes": ["Product"], "onlyNew": true} → Get dataset items → IF availability == "OutOfStock" → Slack message.
  • Make: Apify > Run an Actor → Apify > Get Dataset Items → Google Sheets > Add a Row (map name, price, priceCurrency, availability, url).
  • Zapier: "Apify: Actor Run Finished" trigger → "Google Sheets: Create Spreadsheet Row".
  • Google Sheets / Excel / CSV: export the dataset (Overview view) straight from the run page.
  • Webhooks, Airbyte, Keboola and the other Apify integrations work as well.

Use with AI agents (MCP)

The Actor is ready for the Apify MCP server, so Claude, Cursor, ChatGPT and other agents can call it as a tool: "get the price and rating of these 20 product pages", "list the ingredients of this recipe", "what events does this venue announce next month?".

Add https://mcp.apify.com/?actors=<USERNAME>/structured-data-extractor to your MCP client. Every result contains a short markdown summary, so the agent can read it directly without parsing nested JSON-LD.

FAQ

Does it render JavaScript? No. It reads the raw HTML, which is where almost every site puts its JSON-LD and OpenGraph tags, because search engines and social networks read them there. Markup injected later by JavaScript (some SPAs, some tag-manager setups) is not seen. Those pages come back as noStructuredData and are free.

What is the "main entity"? With schemaTypes, it is the first entity of the first requested type. Without a filter, it is the most specific entity on the page (a Product, Recipe or Event rather than WebSite, BreadcrumbList or Organization). All the other entities are still in entities.

Are numbers normalised? Prices, ratings, counts, salaries and coordinates are converted to numbers ("1.234,50" → 1234.5). Dates and ISO 8601 durations (PT1H30M) are kept exactly as published.

What about blocked websites? If a site refuses the server IP, the page is retried once through a datacenter proxy. CAPTCHAs and anti-bot challenges are never bypassed: those pages are reported as blocked and not charged.

Can I extract every product of a category page? Yes, if the page lists them in its markup (e.g. an ItemList of Product): use "schemaTypes": ["Product"] and read the entities array. To discover the URLs first, pair it with a sitemap extractor.

Is it legal? The Actor only reads public pages, without login, and only the markup the websites publish for machines. You are responsible for how you use the data (copyright, terms of the source websites, personal data rules).

Limits

  • Raw HTML only (no JavaScript rendering). Pages above 3 MB are cut at 3 MB.
  • RDFa support covers RDFa Lite (vocab, typeof, property, resource), which is what schema.org markup uses. Exotic full-RDFa features (CURIE prefix maps, rel/rev chaining) are not interpreted.
  • Websites behind CAPTCHA or JavaScript challenges (some large retailers, sometimes IMDb from datacenter IPs) are reported as blocked, for free.
  • The data is what the website publishes: when a site's markup is wrong or outdated (e.g. a stale price), the output is too.
  • Up to 50 entities per page by default (maxEntitiesPerPage, max 500).