{
  "name": "structured-data-extract",
  "summary": "Fetches a web page and returns its embedded machine-readable data -- JSON-LD, OpenGraph, microdata and meta tags -- plus a normalised merge across all four.",
  "rationale": "It needs the network and a real DOM, and the extraction is the code an agent keeps re-implementing wrong: skipping a broken JSON-LD script instead of throwing, telling og: from name= apart, and walking microdata with its parent/child nesting rule. One call replaces four brittle scrapers.",
  "family": "fetch",
  "price_usd": "0.002",
  "free": false,
  "timeout_ms": 8000,
  "max_timeout_seconds": 29,
  "input_schema": {
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "type": "object",
    "properties": {
      "url": {
        "type": "string",
        "maxLength": 2048,
        "format": "uri",
        "description": "Absolute http(s) URL of the HTML or XHTML page to read, up to 2048 characters; up to 5 redirects are followed and relative URLs resolve against the final URL or its <base href>."
      },
      "types": {
        "description": "Which of jsonld, opengraph, microdata and meta to extract, at least one; omitted means all four, and a type not requested comes back null and is left out of the normalized merge.",
        "minItems": 1,
        "type": "array",
        "items": {
          "type": "string",
          "enum": [
            "jsonld",
            "opengraph",
            "microdata",
            "meta"
          ]
        }
      }
    },
    "required": [
      "url"
    ],
    "additionalProperties": false
  },
  "input_example": {
    "url": "https://grist.tools/samples/web/fieldnotes/notes/first-frost.html"
  },
  "output_example": {
    "url": "https://grist.tools/samples/web/fieldnotes/notes/first-frost.html",
    "source_url": "https://grist.tools/samples/web/fieldnotes/notes/first-frost.html",
    "final_url": "https://grist.tools/samples/web/fieldnotes/notes/first-frost.html",
    "http_status": 200,
    "jsonld": [
      {
        "@context": "https://schema.org",
        "@type": "Article",
        "headline": "The first frost of the season",
        "description": "A light ground frost on the lower beds, measured at dawn.",
        "image": "../icon-32.png",
        "datePublished": "2026-08-24T06:30:00Z",
        "author": {
          "@type": "Organization",
          "name": "Field Notes Editors"
        }
      }
    ],
    "jsonld_total": 1,
    "jsonld_truncated": false,
    "jsonld_parse_errors": 0,
    "opengraph": {
      "og:title": "The first frost of the season",
      "og:type": "article",
      "og:url": "https://grist.tools/samples/web/fieldnotes/notes/first-frost.html",
      "og:image": "https://grist.tools/samples/web/fieldnotes/icon-32.png"
    },
    "microdata": [
      {
        "type": "https://schema.org/Place",
        "properties": {
          "name": "Lower beds",
          "description": "The lowest corner of the garden, where cold air settles first."
        }
      }
    ],
    "microdata_total": 1,
    "microdata_truncated": false,
    "meta": {
      "description": "A light ground frost on the lower beds, measured at dawn.",
      "author": "Field Notes Editors",
      "article:published_time": "2026-08-24T06:30:00Z"
    },
    "normalized": {
      "title": "The first frost of the season",
      "description": "A light ground frost on the lower beds, measured at dawn.",
      "image": "https://grist.tools/samples/web/fieldnotes/icon-32.png",
      "type": "Article",
      "author": "Field Notes Editors",
      "published": "2026-08-24T06:30:00Z"
    },
    "fetched_at": "2026-09-01T12:00:00.000Z"
  },
  "errors": [
    "invalid_input",
    "blocked_target",
    "unreachable_target",
    "upstream_status",
    "upstream_timeout",
    "unsupported_content_type",
    "too_large",
    "unprocessable",
    "internal"
  ]
}