Schema Markup Scraper & SEO Auditor avatar

Schema Markup Scraper & SEO Auditor

Pricing

from $3.00 / 1,000 results

Go to Apify Store
Schema Markup Scraper & SEO Auditor

Schema Markup Scraper & SEO Auditor

Extract JSON-LD, Microdata, RDFa, Open Graph & Twitter Cards. Runs a 0-100 SEO audit โ€” checks canonical, hreflang, headings, image alt, EEAT author signals. Detects 80+ schema.org types including LocalBusiness with NAP, geo coordinates, and Google Place IDs.

Pricing

from $3.00 / 1,000 results

Rating

5.0

(2)

Developer

Richard Feng

Richard Feng

Maintained by Community

Actor stats

8

Bookmarked

193

Total users

24

Monthly active users

3 days ago

Last modified

Share

Extract structured data, metadata, and SEO signals from any web page. Built for technical SEO auditing, local business intelligence, content aggregation, and competitive analysis.

๐Ÿค– Use with AI agents

This Actor is built to be called by software. One URL list in, one record per page out, and a single status field that says whether the run did what you asked.

MCP โ€” expose it as a tool to any MCP-capable agent:

https://mcp.apify.com?tools=autofacts/metadata-scraper

Minimal request โ€” everything except startUrls has a working default:

curl -X POST "https://api.apify.com/v2/acts/autofacts~metadata-scraper/run-sync?token=$APIFY_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "startUrls": [{ "url": "https://example.com/product/123" }] }'

Use run-sync rather than run-sync-get-dataset-items: the response carries both data.defaultDatasetId and data.defaultKeyValueStoreId, and you need the second one to read the SUMMARY record below. run-sync-get-dataset-items returns the rows alone, which leaves an agent unable to tell an empty result from a failed one.

What the user wants โ†’ what to send

The user asks forSendRead from each record
"what schema markup does this page have?"{ startUrls }schemaTypes, linkedData, microdata
"audit this page for SEO"{ startUrls }seoAudit.score, seoAudit.issues
"check the hreflang setup on these pages"{ startUrls, extractGeoData: false, computeSeoScore: false }hreflang.tags, hreflang.hasXDefault, hreflang.issues
"get the business name, address and phone"{ startUrls, extractSeoAnalysis: false }nap, localBusiness, mapReferences
"who wrote this and when?"{ startUrls }authorInfo, articleMetadata
"how will this look when shared?"{ startUrls, extractSeoAnalysis: false, extractGeoData: false, computeSeoScore: false }openGraph, twitterCard, icon
"audit a whole section of a site"{ startUrls, followLinks: true, maxDepth: 2, maxRequestsPerCrawl: 200 }all of the above, one record per page
"does this page use RDFa / microformats?"{ startUrls, extractRdfa: true, extractHCard: true }rdfa, hCards

Run summary โ€” SUMMARY

Every run writes a SUMMARY record to its default key-value store, on the success and the failure path alike:

GET https://api.apify.com/v2/key-value-stores/{defaultKeyValueStoreId}/records/SUMMARY
{
"status": "PARTIAL_RESULTS",
"note": "Some pages were scraped and some URLs failed. โ€ฆ",
"startUrlCount": 3,
"pagesScraped": 2,
"failedUrlCount": 1,
"failures": [
{ "url": "https://unreachable.example/", "reason": "getaddrinfo ENOTFOUND unreachable.example" }
],
"startedAt": "2026-09-16T03:07:11.402Z",
"finishedAt": "2026-09-16T03:07:22.596Z"
}
statusMeaningWhat an agent should do
SUCCESSEvery page fetched produced a recordUse the dataset
PARTIAL_RESULTSSome pages scraped, some URLs failedUse the dataset; report or retry failures
NO_RESULTSURLs were given, none could be fetchedRetry, or check failures for blocks and typos
NO_INPUTNo start URLs were suppliedDo not retry the same input
RUN_FAILEDThe crawl itself erroredAnything already in the dataset is still valid

Two details worth knowing before you compare counts:

  • pagesScraped below startUrlCount with failedUrlCount: 0 means the crawl hit maxRequestsPerCrawl. The status is still SUCCESS โ€” nothing failed, the budget simply ran out. Raise maxRequestsPerCrawl to get the rest.
  • failures lists at most 100 entries; failedUrlCount is always exact. On a large run, treat the list as a diagnostic sample rather than a complete set.

Rules for agents

  • startUrls is the whole contract. This Actor never discovers URLs on its own; it fetches what you give it, plus links it finds only when followLinks is true.
  • One record per page fetched. A record whose linkedData and microdata are empty is a valid, successful result โ€” it means the page declares no structured data. Do not retry it.
  • An empty dataset is not a success here. Because every reachable page yields exactly one record, zero records means nothing was fetched. Check SUMMARY.status, not the row count.
  • A failed URL is never in the dataset. It is in SUMMARY.failures, with the reason.
  • Do not invent field names. The complete field list is in Output fields below and in the Actor's dataset schema; fields absent from a record were switched off or not declared by the page.
  • Turning extractors off does not reduce cost. Billing is one event per dataset item, and a page produces one item regardless of how many extractors ran. Use the toggles for a smaller, cleaner payload, not for a cheaper run.
  • No JavaScript is executed. A URL whose content is rendered client-side returns the shell of the page, which is a correct result for this Actor and a useless one for the user.

๐Ÿ“– What it does

This scraper visits one or more URLs and extracts everything a search engine sees: structured data (JSON-LD, Microdata, RDFa), social meta tags (Open Graph, Twitter Cards), and dozens of SEO signals. It then runs an automated audit and returns a 0-100 SEO score with actionable issues โ€” aligned with Google's 2025 ranking signals and EEAT guidelines.

๐ŸŽฏ Key capabilities

Structured data extraction

  • JSON-LD โ€” Parses all <script type="application/ld+json"> blocks, including nested @graph structures
  • Microdata โ€” Extracts itemscope/itemprop schema.org markup with full nesting support
  • RDFa (opt-in) โ€” Parses typeof/property/vocab attributes with schema.org vocabulary resolution
  • Schema type detection โ€” Identifies all schema.org types present (Product, Article, LocalBusiness, BreadcrumbList, etc.)

Social & meta tags

  • Open Graph โ€” All og:* properties (title, description, image, type, locale, etc.)
  • Twitter Cards โ€” All twitter:* properties with special handling for summary_large_image
  • Dublin Core โ€” DC.* and DCTerms.* academic/institutional metadata
  • Standard meta tags โ€” viewport, description, keywords, robots, theme-color, and all others

SEO analysis

  • Canonical URL โ€” Detects <link rel="canonical">
  • Robots meta โ€” Extracts directives for robots, googlebot, bingbot, etc.
  • Heading hierarchy โ€” Maps H1โ€“H6 structure, counts H1 tags, detects skipped levels
  • Image alt text audit โ€” Counts images with/without alt attributes, calculates coverage percentage
  • Viewport & charset โ€” Verifies mobile-first indexing prerequisites
  • SEO score (0-100) โ€” Automated audit checking 15 Google ranking signals with error/warning/info severity

International SEO

  • Hreflang tags โ€” Extracts all <link rel="alternate" hreflang="..."> with built-in validation:
    • Flags missing x-default fallback
    • Validates ISO 639-1 language codes (catches common mistakes like en-UK โ†’ should be en-GB)
    • Detects missing self-referencing tags
  • Language detection โ€” <html lang>, <meta http-equiv="content-language">, og:locale

EEAT & author signals

  • Author extraction โ€” Pulls author info from JSON-LD (Person type with sameAs links), <meta name="author">, and <a rel="author">
  • Article metadata โ€” datePublished, dateModified, headline, wordCount, publisher from Article/NewsArticle/BlogPosting schema

Local / Geo SEO

  • LocalBusiness extraction โ€” Detects 80+ schema.org LocalBusiness subtypes (Restaurant, Hotel, Dentist, Store, etc.) and extracts NAP, geo coordinates, opening hours, price range
  • NAP (Name/Address/Phone) โ€” From any Organization or LocalBusiness schema
  • Geo meta tags โ€” geo.region, geo.placename, geo.position, ICBM
  • Google Maps references โ€” Embedded map iframes, Place IDs, CID numbers
  • hCard/vCard (opt-in) โ€” .vcard/.h-card microformat contact data
  • Extracts BreadcrumbList schema items with position, name, and URL
  • Validates sequential positions and flags relative URLs

๐Ÿ“‹ Input parameters

ParameterTypeDefaultDescription
startUrlsArray(required)URLs to scrape
proxyObjectApify ProxyProxy configuration
maxRequestsPerCrawlInteger100Maximum pages to scrape (1โ€“100,000)
maxConcurrencyInteger10Parallel pages (1โ€“100)
followLinksBooleanfalseAlso crawl links found on the start pages
maxDepthInteger0Link hops to follow past a start URL (needs followLinks)
extractMetaTagsBooleantrueExtract all meta tags
extractSeoAnalysisBooleantrueSEO signals: canonical, hreflang, robots, headings, author, images, breadcrumbs, Dublin Core, viewport, charset
extractGeoDataBooleantrueGeo tags, LocalBusiness, NAP, Google Maps references
computeSeoScoreBooleantrueRun SEO audit (0-100 score + issues list)
extractRdfaBooleanfalseRDFa structured data (opt-in)
extractHCardBooleanfalsehCard/vCard microformats (opt-in)

๐Ÿ—‚๏ธ Output fields

Each scraped page produces a JSON object with these fields:

Core metadata

FieldTypeDescription
urlStringFinal URL after redirects
titleStringPage <title> content
iconStringFavicon/apple-touch-icon URL
linkedDataArrayJSON-LD structured data blocks
microdataArrayMicrodata (schema.org) items
openGraphObjectOpen Graph properties
twitterCardObjectTwitter Card properties
metaTagsObjectAll other meta tags

SEO analysis (when extractSeoAnalysis is enabled)

FieldTypeDescription
canonicalString/nullCanonical URL
robotsMetaObjectRobots directives ({ robots: "index, follow", googlebot: "noarchive" })
hreflangObject{ tags: [{lang, url}], hasXDefault: bool, issues: string[] }
languageObject{ htmlLang, contentLanguage, ogLocale }
dublinCoreObjectDublin Core metadata
viewportString/nullViewport meta tag content
charsetString/nullCharacter encoding
headingsObject{ headings: [{level, text}], h1Count, issues[] }
imageAuditObject{ totalImages, imagesWithAlt, imagesWithoutAlt, altTexts[], issues[] }
authorInfoObject/null{ name, url, sameAs[], jobTitle, source }
schemaTypesArrayAll schema.org types detected (e.g., ["Product", "BreadcrumbList"])
articleMetadataObject/null{ datePublished, dateModified, headline, description, wordCount, publisher }
breadcrumbsObject/null{ items: [{position, name, url}], issues[] }

Geo / Local SEO (when extractGeoData is enabled)

FieldTypeDescription
geoTagsObject/nullGeo meta tags ({ region, placename, position, icbm })
localBusinessObject/nullLocalBusiness schema data with NAP, geo coordinates, opening hours
napObject/nullName, Address, Phone from Organization/LocalBusiness
mapReferencesObject/null{ googleMapsEmbeds[], placeIds[], cids[] }

SEO audit (when computeSeoScore is enabled)

FieldTypeDescription
seoAuditObject{ score: 0-100, issues: [{severity, code, message}] }

Optional extractors

FieldTypeDescription
rdfaArrayRDFa structured data (when extractRdfa is enabled)
hCardsArrayhCard/vCard contact data (when extractHCard is enabled)

โœ… SEO audit checks

The audit starts at 100 and deducts points for each issue found:

CheckSeverityPointsWhat it catches
Missing <title>Error-10Core ranking signal
Title > 60 charsWarning-5SERP truncation
Missing meta descriptionError-10CTR impact
Description > 160 charsWarning-5SERP truncation
Missing or multiple H1Error-10Content hierarchy
Missing canonical URLWarning-5Duplicate content risk
Missing og:titleWarning-5Social share CTR
Missing og:descriptionWarning-5Social share CTR
Missing og:imageWarning-5Social CTR (40-60% impact)
No structured dataWarning-5Rich results eligibility
Missing faviconWarning-5Brand trust signal
Missing viewportWarning-5Mobile-first indexing
Missing hreflang x-defaultWarning-5International SEO trust
Missing author (on articles)Warning-5EEAT signal
Missing datePublished (on articles)Warning-5Freshness signal
> 50% images without altWarning-5Accessibility + AI
No BreadcrumbList (deep pages)Info-1Navigation hierarchy

๐Ÿ’ก Use cases

Technical SEO audit

Crawl your site and get an instant SEO health check across every page. Identify missing titles, broken heading hierarchies, absent structured data, and more โ€” with a prioritized issues list.

E-commerce competitive analysis

Extract product schema (pricing, availability, reviews, return policies), breadcrumb structures, and rich snippet eligibility from competitor product pages.

Local business intelligence

Scrape LocalBusiness schema from directories, review sites, or business websites. Extract NAP data, opening hours, geo coordinates, Google Place IDs, and CID numbers for lead generation or data enrichment.

International SEO validation

Audit hreflang implementations across multilingual sites. Catch the errors that 75% of implementations contain: missing x-default fallbacks, invalid ISO codes, missing self-references.

EEAT & content analysis

Extract author information, sameAs links to verified profiles, publication dates, and publisher data from article pages. Monitor how well your content signals expertise and authority.

Social media preview testing

Verify how pages will appear when shared on Facebook (Open Graph) and Twitter/X (Twitter Cards). Check for missing images, truncated descriptions, and incomplete metadata.

Content aggregation

Build news aggregators or content feeds by extracting article metadata, publication dates, authors, and descriptions from multiple sources in a single crawl.

๐Ÿ“ค Example output

News article (CNN)

{
"url": "https://edition.cnn.com/2025/04/18/politics/...",
"title": "Supreme Court temporarily pauses deportations under Alien Enemies Act",
"canonical": "https://www.cnn.com/2025/04/18/politics/...",
"language": {
"htmlLang": "en",
"contentLanguage": null,
"ogLocale": "en_US"
},
"hreflang": {
"tags": [
{ "lang": "en-gb", "url": "https://edition.cnn.com/..." },
{ "lang": "en-us", "url": "https://www.cnn.com/..." },
{ "lang": "x-default", "url": "https://edition.cnn.com/..." }
],
"hasXDefault": true,
"issues": ["Missing self-referencing hreflang tag"]
},
"authorInfo": {
"name": "Tierney Sneed, John Fritze",
"url": null,
"sameAs": [],
"jobTitle": null,
"source": "meta"
},
"schemaTypes": ["NewsArticle", "Person", "ImageObject", "Organization", "WebPage", "NewsMediaOrganization"],
"seoAudit": {
"score": 79,
"issues": [
{ "severity": "warning", "code": "TITLE_TOO_LONG", "message": "Title is 94 chars (recommended: max 60)" },
{ "severity": "warning", "code": "DESCRIPTION_TOO_LONG", "message": "Meta description is 267 chars (recommended: max 160)" },
{ "severity": "warning", "code": "MISSING_DATE_PUBLISHED", "message": "Article page missing datePublished (impacts freshness signals)" },
{ "severity": "info", "code": "NO_BREADCRUMBS", "message": "Deep page with no BreadcrumbList schema (helps navigation hierarchy)" }
]
}
}

E-commerce product (Farfetch)

{
"url": "https://www.farfetch.com/shopping/women/jacquemus-les-doubles-sandals-item-28543291.aspx",
"title": "Jacquemus Les Doubles Sandals | Brown | FARFETCH",
"canonical": "https://www.farfetch.com/shopping/women/jacquemus-les-doubles-sandals-item-28543291.aspx",
"schemaTypes": ["ProductGroup", "ImageObject", "Brand", "Product", "Offer", "MerchantReturnPolicy", "UnitPriceSpecification", "BreadcrumbList", "ListItem"],
"breadcrumbs": {
"items": [
{ "position": 1, "name": "Women Home", "url": "/shopping/women/items.aspx" },
{ "position": 2, "name": "Jacquemus", "url": "/shopping/women/jacquemus/items.aspx" },
{ "position": 3, "name": "Shoes", "url": "/shopping/women/jacquemus/shoes-1/items.aspx" },
{ "position": 4, "name": "Heeled Sandals", "url": "/shopping/women/jacquemus/heeled-sandals-1/items.aspx" }
],
"issues": ["Relative URL in breadcrumb position 1: \"/shopping/women/items.aspx\""]
},
"headings": {
"h1Count": 1,
"issues": ["Skipped heading level: h2 to h4"]
},
"imageAudit": {
"totalImages": 6,
"imagesWithAlt": 5,
"imagesWithoutAlt": 1,
"issues": ["1 image(s) missing alt attribute"]
},
"robotsMeta": { "robots": "noindex" },
"seoAudit": { "score": 100, "issues": [] }
}

Wikipedia (RDFa + hCard)

{
"url": "https://en.wikipedia.org/wiki/San_Francisco",
"title": "San Francisco - Wikipedia",
"canonical": "https://en.wikipedia.org/wiki/San_Francisco",
"schemaTypes": ["Article", "Organization", "ImageObject"],
"authorInfo": {
"name": "Contributors to Wikimedia projects",
"source": "json-ld"
},
"articleMetadata": {
"datePublished": "2001-11-13T04:30:40Z",
"dateModified": "2026-03-28T17:14:57Z",
"headline": "consolidated city and county in California, United States",
"publisher": { "name": "Wikimedia Foundation, Inc." }
},
"rdfa": ["... 114 RDFa items extracted ..."],
"hCards": [{ "name": "San Francisco", "... ": "..." }],
"imageAudit": {
"totalImages": 119,
"imagesWithAlt": 43,
"imagesWithoutAlt": 76,
"issues": ["64% of images missing alt text (accessibility + AI understanding)"]
},
"seoAudit": {
"score": 80,
"issues": [
{ "severity": "error", "code": "MISSING_DESCRIPTION", "message": "Page has no meta description" },
{ "severity": "warning", "code": "MISSING_OG_DESCRIPTION", "message": "Missing og:description meta tag" },
{ "severity": "warning", "code": "IMAGES_MISSING_ALT", "message": "64% of images missing alt text" }
]
}
}

๐Ÿ› ๏ธ Technical details

  • Engine: CheerioCrawler (server-side HTML parsing, no JavaScript execution)
  • Runtime: Node.js 22, Apify SDK 3.5.3, Crawlee 3.15.3
  • Performance: Lightweight and fast โ€” no browser overhead
  • Sessions: Automatic session rotation with cookie persistence
  • Proxies: Full proxy support including Apify Proxy residential groups
  • Retries: Up to 3 retries per request with automatic session rotation on blocks
  • Link following: Optional crawling with configurable depth

๐Ÿ’ณ Pricing

This Actor uses pay per event โ€” you are charged per URL audited and saved to the dataset, not for compute time.

EventFree / StarterScale / Business+
URL audited and saved$0.0050$0.0030

What the free plan gets you: Apify's free plan includes $5 of platform credit every month, which is about 1,000 URLs audited per month at no cost. A 10,000-page site audit costs $50 on the free/starter rate, $30 on Scale or above.

There is no per-run start fee. You are never charged for URLs that fail to load. Set Max total charge on the run to cap spend on large crawls.


โš ๏ธ Limitations

  • No JavaScript rendering โ€” Pages that require JS to load content (e.g., SPAs, IMDB) will return minimal data. Use a browser-based scraper for these.
  • Anti-bot protection โ€” Some sites (Yelp, BBC, Medium) may block requests even with residential proxies. Results depend on proxy quality.
  • RDFa complexity โ€” The RDFa extractor handles the common schema.org vocabulary case. Exotic namespace prefixes may not be fully resolved.
  • No performance scoring โ€” Page speed, Core Web Vitals and Lighthouse categories are deliberately out of scope. Measuring them needs a real browser; this Actor is HTTP-only by design, which is what makes it fast and cheap. Pair it with a dedicated performance Actor if you need both.

๐Ÿงฐ Other Actors by autofacts

Apify only auto-recommends Actors in the same category, so here are the ones that actually pair with this scraper:

ActorWhat it's for
Universal Web PrinterRender the audited page to PDF/PNG for the report
YouTube Subtitle & Transcript ScraperPull video captions as clean text for content and RAG pipelines
Shopify Store LeadsFind Shopify stores to audit in bulk
Shopify ScraperFull product and collection data once a store is worth a closer look

All of them: apify.com/autofacts