# Link Preview API

> Title, description, image, favicon and feeds for any public URL.

Fetches a page and returns the metadata a chat app, CMS or newsletter tool needs to show a rich preview: Open Graph and Twitter card tags, the canonical URL, icons, language, author, dates, theme colour, RSS and Atom feeds and the oEmbed endpoint. Results are cached for an hour.

- **Endpoint:** `GET https://api.zactonz.com/unfurl/`
- **Category:** Web
- **Version:** 1
- **Status:** stable
- **Authentication:** `Authorization: Bearer YOUR_API_KEY`
- **Reference page:** https://developers.zactonz.com/apis/link-preview/

## Parameters

Send parameters in the query string.

| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| `url` | string | yes |  | The page to preview. `https://` is assumed when the scheme is omitted. |
| `render` | boolean | no | `false` | `1` loads the page in a headless browser before reading its tags. |
| `verify_image` | boolean | no | `false` | `1` downloads the preview image to confirm it exists and to report its real dimensions and type. |
| `fresh` | boolean | no | `false` | `1` bypasses the one-hour cache. |

## Example request

```bash
curl "https://api.zactonz.com/unfurl/?url=https%3A%2F%2Fzactonz.com%2Fproducts%2F&render=&verify_image=&fresh=" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

## Response

OK

| Field | Type | Description |
|---|---|---|
| `status` | integer | `200` on success. |
| `data` | object | The result. |
| `data.url` | string | URL as requested. |
| `data.final_url` | string | URL after redirects. |
| `data.status` | integer | HTTP status of the page. |
| `data.title` | string | Best title from Open Graph, Twitter or the title tag. |
| `data.description` | string | Best description. |
| `data.site_name` | string | Site name. |
| `data.type` | string | Open Graph type. |
| `data.canonical` | string | Canonical URL. |
| `data.image` | object | Preview image: `url`, `width`, `height`, `alt`, `type`, and with `verify_image` also `verified` and `bytes`. |
| `data.favicon` | string | Best icon URL. |
| `data.icons` | array of object | All declared icons with `rel`, `sizes` and `type`. |
| `data.language` | string | Value of `<html lang>`. |
| `data.locale` | string | Open Graph locale. |
| `data.author` | string | Author. |
| `data.published_time` | string | Publication date as declared. |
| `data.modified_time` | string | Modification date as declared. |
| `data.keywords` | array of string | Meta keywords. |
| `data.theme_color` | string | Theme colour. |
| `data.twitter` | object | `card`, `site`, `creator`. |
| `data.feeds` | array of object | RSS, Atom or JSON feeds with `url`, `type`, `title`. |
| `data.oembed` | string | oEmbed endpoint if declared. |
| `data.rendered` | boolean | Whether a browser was used. |
| `data.from_cache` | boolean | Whether the answer came from the cache. |

```json
{
    "status": 200,
    "data": {
        "url": "https://zactonz.com/products/",
        "final_url": "https://zactonz.com/products/",
        "status": 200,
        "title": "Products - Zactonz Technologies",
        "description": "Software built, run and supported by Zactonz: VitalLens, Zotiba, ClassTools24, NeuronFlow, WordPress plugins and themes, and cPanel & WHM plugins.",
        "site_name": null,
        "type": null,
        "canonical": "https://zactonz.com/products/",
        "image": null,
        "favicon": "https://zactonz.com/favicon.ico",
        "icons": [],
        "language": "en-us",
        "locale": null,
        "author": null,
        "published_time": null,
        "modified_time": null,
        "keywords": [],
        "theme_color": null,
        "twitter": {
            "card": null,
            "site": null,
            "creator": null
        },
        "feeds": [],
        "oembed": null,
        "rendered": false,
        "from_cache": false
    }
}
```

## Status codes

The outcome is reported in the JSON `status` field. General rules: https://developers.zactonz.com/apis/errors.md

| status | Meaning | Description |
|---|---|---|
| `400` | Bad request | `url` is missing, malformed, or points at a host that is not reachable from here. |
| `413` | Too large | The page is larger than 2 MB. |
| `415` | Not HTML | The URL does not serve an HTML document. |
| `422` | Unreachable | The page could not be fetched, or it answered with an error status given in `upstream_status`. |
| `401` | Unauthorized | The Authorization header is missing or the key is not recognised. |
| `403` | Forbidden | The key is not licensed for this product. |
| `429` | Too many requests | The per-minute rate or the plan quota is exhausted. Retry after the seconds given in `Retry-After`. |

## Notes

Pages are fetched with a normal browser `User-Agent` and a 2 MB limit. Set `render=1` for sites that only populate their tags with JavaScript; a rendered call costs 5 units instead of 1. Hosts that resolve to private or loopback addresses are refused.
