switch402

URL Metadata and Link Preview API: OpenGraph, Twitter Tags, JSON-LD for $0.001

/v1/metadata fetches a public HTML page and returns what a link preview needs: title, meta description, canonical URL, language, OpenGraph and Twitter tags and parsed JSON-LD blocks. $0.001 USDC on Base per call, paid over x402, charged only on success.

  • Everything for a preview card

    title, description, canonical, lang, og (OpenGraph tags, e.g. og.title), twitter (Twitter card tags) and json_ld (parsed blocks; json_ld_invalid counts the ones that failed to parse).

  • Final URL after redirects

    final_url shows where the page landed, after at most 5 redirects.

  • Limits

    Public http(s) HTML pages on default ports only, 8 s per fetch, 20 s per call, 2 MB per page.

  • Not charged on failure

    A blocked URL (400), a non-HTML page (422) or a fetch failure (502) is not charged.

Cost: $0.001 per call. Previewing 2,000 links a month costs $2.00.

Code examples

curl: unpaid call shows the price (HTTP 402, $0.001)

curl -i -G https://api.switch402.com/v1/metadata \
  -H 'User-Agent: my-agent/1.0' \
  --data-urlencode 'url=https://example.com'
# 200 after payment: {"url", "final_url", "title", "description", "canonical", "lang",
#   "og": {...}, "twitter": {...}, "json_ld": [...], "json_ld_invalid", "truncated", "ms"}

Python: build a link preview card

# pip install "x402[requests,evm]"
import os
from eth_account import Account
from x402 import x402ClientSync
from x402.http.clients import x402_requests
from x402.mechanisms.evm import EthAccountSigner
from x402.mechanisms.evm.exact import ExactEvmScheme

client = x402ClientSync()
client.register("eip155:8453", ExactEvmScheme(signer=EthAccountSigner(Account.from_key(os.environ["AGENT_KEY"]))))
session = x402_requests(client)
session.headers["User-Agent"] = "my-agent/1.0"

def link_preview(url: str) -> dict:
    """Title, description and image for a preview card ($0.001 per successful call)."""
    r = session.post("https://api.switch402.com/v1/metadata", json={"url": url})
    r.raise_for_status()
    m = r.json()
    og = m.get("og") or {}
    return {
        "url": m.get("canonical") or m["final_url"],
        "title": og.get("title") or m.get("title"),
        "description": og.get("description") or m.get("description"),
        "image": og.get("image"),
    }

MCP: the metadata tool

curl -s -X POST https://api.switch402.com/mcp -H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' -H 'User-Agent: my-agent/1.0' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"metadata","arguments":{"url":"https://example.com"}}}'

FAQ

What does a call cost if the page fails?
Nothing. A blocked URL, a page that is not HTML or a fetch failure is not charged.
Does it return the preview image file?
It returns the image URL from the OpenGraph tags as published on the page, not the image itself.
Is this the same as a link preview API?
Yes for the data: the fields a preview card needs come back in one call. Rendering the card is up to your app.

Related

More API pages