# JSON-LD Extractor (/docs/experiments/json-ld-extractor)



Fetch a webpage and extract `application/ld+json` structured data blocks for Schema.org / rich-results debugging from Cloudflare's edge.

## Features [#features]

* Parses all `script[type="application/ld+json"]` blocks
* Collects `@type` values including nested `@graph`
* Reports invalid JSON blocks without failing the whole response
* Caps extraction at 25 script blocks
* Stateless; no bindings required

## API Reference [#api-reference]

### GET /extract [#get-extract]

Fetches HTML and returns parsed JSON-LD blocks plus discovered types.

<TypeTable
  type="{
  url: {
    description: &#x22;Page URL (must be http or https)&#x22;,
    type: &#x22;string&#x22;,
    required: true,
  },
}"
/>

#### Example Request [#example-request]

```bash
curl "https://your-worker.workers.dev/extract?url=https://www.cloudflare.com"
```

#### Success Response [#success-response]

**`url`** `string`

Final page URL after redirects

**`count`** `number`

Number of JSON-LD script blocks found

**`types`** `string[]`

Sorted unique `@type` values across all blocks (including `@graph`)

**`blocks`** `array`

Per-block results with `index`, `types`, `data`, and optional `parseError`

```json
{
  "url": "https://www.cloudflare.com/",
  "count": 2,
  "types": ["Organization", "WebSite"],
  "blocks": [
    {
      "index": 0,
      "types": ["Organization"],
      "data": {
        "@context": "https://schema.org",
        "@type": "Organization",
        "name": "Cloudflare"
      }
    },
    {
      "index": 1,
      "types": ["WebSite"],
      "data": {
        "@context": "https://schema.org",
        "@graph": [{ "@type": "WebSite", "name": "Cloudflare" }]
      }
    }
  ]
}
```

#### Error Response [#error-response]

```json
{
  "error": "Expected HTML, got content-type: application/json",
  "code": "NOT_HTML"
}
```

#### Error Codes [#error-codes]

* `400` - Missing or invalid `url` (`INVALID_URL`)
* `400` - Response was not HTML (`NOT_HTML`)
* `502` - Fetch failed (`FETCH_ERROR`)

## Use Cases [#use-cases]

* Debug rich results / Schema.org markup
* Inventory Organization, Product, Article entities on a site
* Complement Open Graph previews with structured data
* Build SEO auditing tools on Workers

## Limitations [#limitations]

* Does not execute JavaScript-injected JSON-LD
* Caps extraction at 25 script blocks
* Does not validate against Schema.org vocabularies
* Invalid JSON blocks are reported via `parseError` rather than failing the request

## Deployment [#deployment]

<Steps>
  <Step>
    ### Click the deploy button [#click-the-deploy-button]

    [![Deploy to Cloudflare Workers](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/shrinathsnayak/cloudflare-experiments/tree/main/apps/experiments/json-ld-extractor)
  </Step>

  <Step>
    ### Deploy [#deploy]

    Follow the deployment wizard. No bindings or secrets required.
  </Step>

  <Step>
    ### Test your deployment [#test-your-deployment]

    ```bash
    curl "https://your-worker.workers.dev/extract?url=https://example.com"
    ```
  </Step>
</Steps>

## Local Development [#local-development]

```bash
cd apps/experiments/json-ld-extractor
npm install
npm run dev
```

Test locally:

```bash
curl "http://localhost:8787/extract?url=https://www.cloudflare.com"
```

## Cloudflare Features Used [#cloudflare-features-used]

* **[Workers](https://developers.cloudflare.com/workers/)** - Edge compute runtime
* **[Fetch API](https://developers.cloudflare.com/workers/runtime-apis/fetch/)** - HTML retrieval from the edge

## Next Steps [#next-steps]

<Cards>
  <Card title="Social Preview Inspector" href="/docs/experiments/social-preview-inspector">
    Preview Open Graph and Twitter cards
  </Card>

  <Card title="Website Metadata Extractor" href="/docs/experiments/website-metadata-extractor">
    Extract title, description, and canonical URL
  </Card>
</Cards>
