Open Graph API

A plain JSON endpoint that reads any URL’s Open Graph and Twitter card tags — title, description, image (fetched and validated, with dimensions) and a checklist of what’s missing or off. Built for scripts, CI checks and AI agents. Free, no key, CORS-enabled.

Endpoint

GET https://api.poly.io/og?url={URL}

Parameters

NameRequiredDescription
urlYesThe page to inspect, http or https. URL-encode it.
uaNoFetch as a platform’s crawler — facebook, x, linkedin, slack, discord or browser. Sites serve different HTML by User-Agent (consent walls, bot gates), so this reproduces what that platform actually reads. Defaults to our own crawler.

Example

$ curl 'https://api.poly.io/og?url=https%3A%2F%2Fexample.com'
{ "ok": true, "finalUrl": "https://example.com/", "host": "example.com", "title": "Example Domain", "description": "Illustrative example for use in documents.", "siteName": "Example", "card": "summary_large_image", "imageUrl": "https://example.com/og.png", "imageOk": true, "imageWidth": 1200, "imageHeight": 630, "checks": [ { "level": "ok", "message": "Title present (14 chars)." }, { "level": "ok", "message": "Image is 1200×630." }, { "level": "warn", "message": "No description — set og:description." } ] }

Response

Always HTTP 200 with a JSON body. Check the ok field, not the status code (see Errors & limits).

FieldTypeDescription
okbooleantrue on success; false with an error string if the URL couldn’t be read.
errorstringPresent only when ok is false — a human-readable reason.
finalUrlstringThe URL after following redirects.
hoststringHostname of finalUrl.
titlestringog:title, falling back to twitter:title then the page <title>.
descriptionstringog:description, falling back to twitter:description.
siteNamestringog:site_name, if set.
cardstringtwitter:card type (e.g. summary_large_image), if set.
imageUrlstringResolved og:image / twitter:image (absolute URL).
imageOkbooleanWhether the image was fetched and is a real image, server-side.
imageWidth, imageHeightnumberPixel dimensions when the image could be read (PNG, JPEG, GIF, WebP); otherwise omitted.
checksarrayDiagnostics — see below.

checks

Each entry is { "level": …, "message": … }. message is human-readable; key off level in code:

levelMeaning
tipOptional best-practice most good sites still skip (og:image:alt, og:image:width/height, og:site_name) — worth doing, not a fault.
okPresent and within sensible bounds.
warnRenders, but degraded — a title that truncates, an http or under-sized image, a missing description.
errorWill visibly break the card — no title, or no image at all.

The thresholds are grounded in the Open Graph protocol (which tags are required vs optional) and the platform docs (Facebook, X’s Cards, LinkedIn) for sizes and truncation — then sanity-checked against a corpus of real sites, so well-built pages stay quiet and only genuine problems flag.

Errors & limits

  • Application errors (bad URL, unreachable host, blocked address) return HTTP 200 with { "ok": false, "error": "…" } — so a single check is enough; you needn’t branch on status codes.
  • Rate limiting. A shared, fair-use limit (a few requests/second). Sustained abuse returns HTTP 429; responses are cached ~5 minutes per URL, so repeat calls are cheap.
  • SSRF-guarded. It won’t fetch private, loopback, link-local or cloud-metadata addresses, and re-checks every redirect hop.
  • CORS. Access-Control-Allow-Origin: * — callable straight from browser JavaScript.

Need more than fair use?

This is free for everyone. If you want it under load — higher limits, an SLA, or the same approach turned into an API of your own — that’s what does.

Talk to us Back to the tool