Page diff Beta
Diffs two live pages field by field in a single call — staging vs production, before vs after a deploy, or your page vs a competitor's. It fetches both URLs, fingerprints them, and returns a structured change list that names which specific links and images were added or removed, not just that a count moved.
Both URLs are SSRF-validated independently before either is fetched. Two fetches, one request against your quota. Static analysis of the served HTML; no browser is involved.
Fields compared: title, meta description, H1, canonical, word count, HTTP status, Open Graph title, Open Graph description, indexing directive, heading outline, structured-data types, detected prices, body text, and the added/removed internal links, external links and images.
Authentication
Send your API key as an X-API-Key header, or as a key query parameter. Available on every plan, including Free — plans differ only in requests per day. This call costs one request against your daily quota, which is shared across every key on the account. See Authentication.
Query parameters
| Name | Type | Description |
|---|---|---|
url required | string | The "before" / baseline page. |
compare required | string | The "after" / comparison page. Alias: compare_url. Bare domains default to https://; maximum 2,048 characters. |
key optional | string | Your API key, if not sent as the X-API-Key header. |
Request
Response
- {
- "url": "https://staging.example.com/p",
- "compare": "https://example.com/p",
- "changed": true, "changeCount": 4,
- "badges": ["Title", "H1 heading", "Headings", "Word count"],
- "changes": [
- { "field": "title", "label": "Title", "cat": "meta", "kind": "changed",
- "old": "Best Coffee Beans 2026", "new": "New Title" },
- { "field": "internalLinks", "label": "Internal links", "cat": "structure",
- "kind": "changed", "old": 22, "new": 20,
- "added": [], "removed": ["https://example.com/old-page"] }
- ],
- "before": { "…": "full page-signals object for url" },
- "after": { "…": "full page-signals object for compare" }
- }
Response fields
| Field | Type | Description |
|---|---|---|
changed | boolean | Whether anything differs. When false, changes and badges are both []. |
badges | string[] | Short human labels for the categories that changed — handy for a notification subject line. |
changes[] | array | One entry per changed field: field, label, cat, kind, old and new. List fields also carry added and removed, each capped at 60 entries. |
before / after | object | The full page-signals fingerprint for each URL, so you can store them without a second call. |
Errors
| Status | When |
|---|---|
400 | compare is missing, or is longer than 2,048 characters. |
401 | Missing or invalid API key. |
403 | Either URL is a private, loopback or cloud-metadata address. Both are checked independently. |
429 | Burst rate limit (60 req/10s per IP, 30 req/10s per key) or your daily quota. See Rate limits. |
502 | One of the two URLs could not be fetched. |
503 | The signal engine is unavailable on this server. This check runs before authentication. |
Errors return { "error": "…" }; see Errors.