Skip to content

About

RESTful API to extract Open Graph metadata, favicons, and rich media info from any URL — with specialized providers for YouTube and Twitter/X. Built with Hono on Cloudflare Workers.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Repository files navigation

Metadata API

CI Deploy Live Version License

A fast RESTful API to extract Open Graph, oEmbed, favicons, and rich media metadata from any URL — with specialized providers for YouTube and Twitter/X.

Built with Hono on Cloudflare Workers, running on the edge with global low latency. No API key required for the public instance.


Table of Contents

Features

  • General Sites: Extracts title, description, keywords, Open Graph image, Twitter Card image, and favicon from any website.
  • Specialized Providers:
    • YouTube: Full video metadata via oEmbed — title, author, thumbnails, embed HTML, and dimensions.
    • Twitter/X: Tweet content, author info, media (images/videos), and engagement stats, via the fxtwitter API.
  • Edge-native: Runs on Cloudflare's global network — responses are served close to your users.
  • Robust error handling: Consistent JSON error payloads for invalid URLs, upstream failures, and non-success responses.
  • CORS-friendly: Preconfigured for common frontend origins (localhost, Vercel previews, and production sites).

Quick Start

Request metadata for any URL:

curl "https://metadata-api.carllos-nc.workers.dev/metadata?url=https://hono.dev/"

Try it in your browser:

https://metadata-api.carllos-nc.workers.dev/metadata?url=https://www.youtube.com/watch?v=dQw4w9WgXcQ

JavaScript example:

const res = await fetch(
  "https://metadata-api.carllos-nc.workers.dev/metadata?url=https://hono.dev/"
);
const meta = await res.json();
console.log(meta.title, meta.image, meta.favicon);

Response Formats

The API returns JSON tailored to the content source.

General Website

GET /metadata?url=https://hono.dev/

{
  "url": "https://hono.dev",
  "title": "Hono - Web framework built on Web Standards",
  "description": "Web framework built on Web Standards for Cloudflare Workers, Fastly Compute, Deno, Bun, Vercel, Node.js, and others. Fast, but not only fast.",
  "keywords": null,
  "image": "https://hono.dev/images/hono-title.png",
  "favicon": "https://hono.dev/favicon.ico"
}
Field Type Description
url string The resolved URL (trailing slash stripped)
title string From <title>, og:title, or twitter:title
description string From meta[name=description], twitter:description, or OG
keywords string From meta[name=keywords]
image string From og:image or twitter:image
favicon string Resolved favicon URL from link[rel*=icon] and fallbacks

YouTube Video

GET /metadata?url=https://www.youtube.com/watch?v=dQw4w9WgXcQ

{
  "title": "Rick Astley - Never Gonna Give You Up (Official Video) (4K Remaster)",
  "author_name": "Rick Astley",
  "author_url": "https://www.youtube.com/@RickAstleyYT",
  "type": "video",
  "height": 113,
  "width": 200,
  "version": "1.0",
  "provider_name": "YouTube",
  "provider_url": "https://www.youtube.com/",
  "thumbnail_height": 360,
  "thumbnail_width": 480,
  "thumbnail_url": "https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg",
  "html": "<iframe ...></iframe>",
  "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
}

Powered by YouTube's oEmbed endpoint. Accepts youtube.com/watch, youtu.be/, and m.youtube.com URLs.

Twitter/X Post

GET /metadata?url=https://x.com/anime_shots/status/2008237217089540228

{
  "code": 200,
  "message": "OK",
  "tweet": {
    "url": "https://x.com/anime_shots/status/2008237217089540228",
    "id": "2008237217089540228",
    "text": "Summer Time Rendering (2022)",
    "raw_text": { "text": "...", "facets": [...] },
    "author": {
      "name": "Anime Shots",
      "screen_name": "anime_shots",
      "followers": 1432288
    },
    "media": {
      "all": [...],
      "videos": [...]
    },
    "replies": 7,
    "retweets": 139,
    "likes": 3426,
    "views": 696221
  }
}

Accepts both twitter.com and x.com status URLs. The full payload (with all media variants, stats, and created_at) is documented in the fxtwitter API.

Error Handling

All errors return JSON with a consistent shape:

{ "error": true, "message": "..." }
Status Cause
400 Missing or invalid url query parameter (must be a valid HTTP(S) URL)
403 Request blocked by CSRF middleware (missing Origin/Referer)
502 Upstream fetch failed (network error) or target returned non-success
500 Unexpected internal error

Example:

$ curl "https://metadata-api.carllos-nc.workers.dev/metadata?url=not-a-url"
{ "error": true, "message": "The URL must be a valid HTTP/HTTPS URL." }

API Reference

GET /

Returns API metadata (author, repo, description, version).

GET /metadata

Fetch metadata for a URL. The provider is auto-detected.

Query parameters:

Name Type Required Description
url string Yes A valid HTTP/HTTPS URL to inspect

Provider detection:

URL pattern Provider
youtube.com, youtu.be, m.youtube.* YouTube (oEmbed)
twitter.com/*/status/*, x.com/*/status/* Twitter/X (fxtwitter)
anything else Generic scraper

Full request/response examples are in docs/api.md.

Self-Hosting

This API runs on Cloudflare Workers and can be deployed to your own account in minutes.

Prerequisites

Steps

git clone https://github.com/carllosnc/metadata-api.git
cd metadata-api
bun install

bun run dev          # local dev with --remote (uses real Cloudflare backend)
bun run test         # run unit tests
bun run typecheck    # type-check
bun run deploy       # deploy to your Cloudflare account

For CI/CD, set the CLOUDFLARE_API_TOKEN repository secret and reuse the included workflow — it runs tests on every PR and deploys on push to master.

See docs/development.md for details.

Tech Stack

Project Structure

src/
├── index.ts              # Hono app, routes, error handler
├── middlewares/
│   └── validation.ts     # Zod-based URL query validator
└── providers/
    ├── any-site.ts       # Generic OG/Twitter-card scraper
    ├── youtube.ts        # YouTube oEmbed provider
    └── twitter.ts        # Twitter/X via fxtwitter
test/
└── unit.spec.ts          # Unit tests (with mocked upstream fetch)
docs/
├── api.md                # Endpoint reference
└── development.md        # Setup, testing, deployment

Contributing

Contributions are welcome! Please open an issue first to discuss new providers or breaking changes.

  1. Fork the repo and create a feature branch.
  2. Run bun install, bun run test, and bun run typecheck before submitting.
  3. Open a Pull Request — CI will run tests automatically.

License

MIT © Carlos Costa

About

RESTful API to extract Open Graph metadata, favicons, and rich media info from any URL — with specialized providers for YouTube and Twitter/X. Built with Hono on Cloudflare Workers.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages