FrameThrower API
Curated film frames, searchable by concept, color, mood, composition, and image similarity. Built for agents, creative tools, and production pipelines.
Every response returns metadata, thumbnail URLs, and deep links — never raw image bytes. Reference use, with attribution.
Get Started
The FrameThrower API gives you programmatic access to the same cinematography reference library that filmmakers use on the website — text search, image search, color matching, craft-attribute filtering, and a growing film catalog. It's designed to be read by humans, agents, and LLMs alike.
Create a FrameThrower account
Complete onboarding
Subscribe to a paid plan
Create an API token
Make your first request
curl -X POST https://framethrower.ai/api/v1/search \
-H "Authorization: Bearer ft_YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"query": "neon-lit rainy street at night", "limit": 5}'Or from JavaScript, with the official SDK:
npm install framethrower-ai
What You Can Build
The API is built for creative workflows. Here are things you (or your agent) can do:
Script → Visual References
Hand the API a screenplay or scene description. For each scene, search by mood, lighting, and setting to find matching cinematography references. Build a lookbook automatically.
// Scene: "INT. WAREHOUSE - NIGHT. Rain hammers the skylights.
// A single fluorescent tube flickers over the interrogation chair."
const scene = await fetch("https://framethrower.ai/api/v1/search", {
method: "POST",
headers: { "Authorization": "Bearer ft_...", "Content-Type": "application/json" },
body: JSON.stringify({
query: "warehouse interior night rain flickering fluorescent interrogation",
limit: 10
})
}).then(r => r.json());
// Refine: find more like the best match
const similar = await fetch("https://framethrower.ai/api/v1/similar", {
method: "POST",
headers: { "Authorization": "Bearer ft_...", "Content-Type": "application/json" },
body: JSON.stringify({ frameId: scene.data[0].id, mode: "visual", limit: 5 })
}).then(r => r.json());Color Palette Matching
Start with a hex color or palette from your brand guidelines or mood reference. Find frames that match those tones — useful for pitch decks, site hero sections, or color-grading references.
// Find frames matching a warm amber + deep teal palette
const res = await fetch("https://framethrower.ai/api/v1/search/color", {
method: "POST",
headers: { "Authorization": "Bearer ft_...", "Content-Type": "application/json" },
body: JSON.stringify({ colors: ["#e8a87c", "#1b4332"], limit: 10 })
}).then(r => r.json());Cinematography Study
Explore how a specific director or DP uses light, lens, and framing. Browse by craft attributes — no text query needed — to find every anamorphic close-up, every high-key daylight wide, every Deakins night exterior.
// All anamorphic night exteriors by Roger Deakins' regular directors
const res = await fetch("https://framethrower.ai/api/v1/browse", {
method: "POST",
headers: { "Authorization": "Bearer ft_...", "Content-Type": "application/json" },
body: JSON.stringify({
lens_character: "anamorphic",
setting: "exterior",
time_of_day: "night",
limit: 20
})
}).then(r => r.json());Reference Images for Creative Briefs
Building a site, app, or campaign? Drop in a reference image and find frames with similar composition, color, and mood. Use the results as a shared visual language with your team or client.
// "Find frames that look like this reference photo"
const res = await fetch("https://framethrower.ai/api/v1/search/image", {
method: "POST",
headers: { "Authorization": "Bearer ft_...", "Content-Type": "application/json" },
body: JSON.stringify({
imageUrl: "https://example.com/my-reference.jpg",
limit: 10
})
}).then(r => r.json());Connect
REST API (direct integration)
Use your API token as a Bearer token in the Authorization header. All endpoints accept JSON and return JSON.
Authorization: Bearer ft_your_token_here Content-Type: application/json
From an AI agent (Claude, ChatGPT, Cursor, etc.)
If you're using an AI agent that supports custom tools or API integrations, configure it with:
https://framethrower.ai/api/v1Bearer ft_your_tokenhttps://framethrower.ai/developersPoint your agent at this page (/developers) — it can read the endpoint reference and examples to understand what's available. The agent makes requests on your behalf using your token, so it has the same access as you do on the website.
OpenAPI / tool definitions
For agents that consume OpenAPI specs or tool schemas, you can describe each endpoint as a tool. Here's a minimal tool definition for search:
{
"name": "framethrower_search",
"description": "Search FrameThrower's film frame library by concept, mood, lighting, color, or composition. Returns thumbnails + metadata + deep links. Use for finding visual references.",
"parameters": {
"type": "object",
"properties": {
"query": { "type": "string", "description": "Natural language search (e.g. 'overhead dinner table warm candlelight')" },
"limit": { "type": "integer", "minimum": 1, "maximum": 50, "default": 10 }
},
"required": ["query"]
}
}All Endpoints
Base URL: https://framethrower.ai/api/v1. All responses use { data, meta } format.
/searchText search — concept, mood, scene, composition
/search/imageImage search — find frames matching a reference image
/search/colorColor search — find frames by hex color or palette
/browseBrowse by craft — filter by shot type, lens, lighting, director, genre
/similarSimilar frames — find more like a specific frame
/frames?id=...Frame detail — full metadata for a single frame
/frames/randomRandom frames — diverse sample for inspiration or seeding
/suggest?q=...Autocomplete — match film titles and people by name
/filmsFilm catalog — paginated, searchable by title or director
/films/:slugFilm detail — plot, runtime, palette, sample frames
/films/frames?slug=...Film frames — all frames for a specific film
Text Search
POST /api/v1/search
Search the frame library with natural language. Describe a mood, scene, composition, or visual — the search understands cinematography.
{
"query": "neon-lit rainy street at night",
"limit": 20, // 1-50, default 20
"mode": "hybrid" // "hybrid" | "semantic" | "description"
}Modes: hybrid (default) fuses visual + text embeddings. semantic uses image-derived embeddings. description searches text metadata only.
Image Search
POST /api/v1/search/image
Find frames that match a reference image by visual similarity, color, and semantic meaning.
{ "imageUrl": "https://example.com/reference.jpg", "limit": 20 }JavaScript SDK
framethrower-ai wraps every endpoint on this page — same token, no HTTP plumbing. TypeScript types are bundled.
npm install framethrower-ai
import FrameThrower from 'framethrower-ai'
const ft = new FrameThrower('ft_YOUR_TOKEN')
// Search by text, colour, or image
const frames = await ft.search('neon rain at night')
const warm = await ft.searchByColor(['#e8a87c', '#1b4332'])
const like = await ft.searchByImage('https://example.com/photo.jpg')
// Browse by craft, then follow a frame into its film
const shots = await ft.browse({ shot_type: 'close-up', lens_character: 'anamorphic' })
const detail = await ft.frame(frames[0].id) // detail.prompt is a composed image prompt
const more = await ft.similar(frames[0].id, { mode: 'visual' })
const films = await ft.films({ q: 'kubrick', sort: 'frames' })
const film = await ft.film(films[0].slug)Source and full reference: npmjs.com/package/framethrower-ai.
Color Search
POST /api/v1/search/color
Find frames dominated by specific colors. Pass one hex color or a palette of up to 6.
// Single color
{ "color": "#e94560" }
// Palette (blended)
{ "colors": ["#e94560", "#1a1a2e", "#16213e"], "limit": 20 }Browse by Craft
POST /api/v1/browse
Filter frames by cinematography attributes — no text query needed. Combine any filters. This is the unique surface: search by how a shot was made, not just what it shows.
{
"shot_type": "close-up", // or "wide", "medium", "extreme-close-up"
"lens_character": "anamorphic", // or "spherical", "vintage_soft"
"setting": "exterior", // or "interior"
"time_of_day": "night", // or "day", "golden_hour", "blue_hour"
"camera_angle": "low_angle", // or "high_angle", "eye_level", "overhead"
"visual_style": "noir", // or "naturalistic", "stylized"
"director": "Denis Villeneuve",
"genre": "Science Fiction",
"era": "2010s",
"year_min": 2010,
"year_max": 2025,
"limit": 20
}Similar Frames
POST /api/v1/similar
Find frames similar to one or more reference frames. The "more like this" flow.
// Single frame
{ "frameId": "abc123", "mode": "semantic", "limit": 20 }
// Multiple frames (averaged — finds the centroid)
{ "frameIds": ["abc", "def", "ghi"], "mode": "visual", "limit": 20 }
// Modes: "semantic" | "visual" | "color"Frame Detail
GET /api/v1/frames?id=FRAME_ID
Full metadata for a single frame — film info, cinematography attributes, colors, mood, and a ready-to-use AI image prompt.
// Response shape
{
"data": {
"id": "abc123",
"imageUrl": "https://frames.shotspot.pro/core/...",
"thumbUrl": "https://frames.shotspot.pro/thumb/...",
"deepLink": "https://framethrower.ai/#frame/abc123",
"prompt": "A lone figure walks through dense orange haze toward a distant structure. Set in exterior, day. Diffused amber backlight with atmospheric haze. Desaturated warm tones dominated by deep orange and ochre. Naturalistic style with a melancholy, atmospheric, isolation mood.",
"film": {
"title": "Blade Runner 2049", "year": 2017,
"director": "Denis Villeneuve", "dp": "Roger Deakins",
"genres": ["Science Fiction", "Drama"],
"tmdbId": 335984, "imdbId": "tt1856101"
},
"metadata": {
"sceneDescription": "A lone figure walks through orange haze...",
"shotType": "wide", "cameraAngle": "eye_level",
"lensCharacter": "anamorphic",
"lightingKey": "low_key",
"lightingDescription": "Diffused amber backlight with atmospheric haze",
"moods": ["melancholy", "atmospheric", "isolation"],
"colorPalette": ["#c45a28", "#1a1a2e", "#e8a87c"],
"era": "2010s", "setting": "exterior", "timeOfDay": "day"
}
}
}Random Frames
GET /api/v1/frames/random?limit=20
Get a diverse random sample. Useful for seeding a UI, inspiration, or sampling the catalog.
Autocomplete
GET /api/v1/suggest?q=kub
Fuzzy-match film titles and director/DP names. Returns up to 5 films and 3 people.
// Response
{
"data": {
"films": [
{ "type": "film", "title": "2001: A Space Odyssey", "year": 1968,
"director": "Stanley Kubrick", "posterUrl": "...", "imdbId": "..." }
],
"people": [
{ "type": "person", "name": "Stanley Kubrick", "slug": "stanley-kubrick",
"portraitUrl": "...", "filmCount": 12 }
]
}
}Film Catalog
GET /api/v1/films?page=1&per_page=50&q=kubrick
Browse the full film catalog. Paginated, filterable by title or director name.
Film Detail
GET /api/v1/films/:slug
Full detail for a film — plot, runtime, MPAA rating, dominant color palette, and sample frames.
GET /api/v1/films/blade-runner-2049-2017
Film Frames
GET /api/v1/films/frames?slug=blade-runner-2049-2017
Get all frames for a specific film (up to 500). Each includes a thumbnail, deep link, and scene description.
Full Examples
curl — search and refine
# Search
curl -s -X POST https://framethrower.ai/api/v1/search \
-H "Authorization: Bearer ft_YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"query": "overhead shot dinner table warm light"}' \
| jq '.data[:3] | .[] | {title: .film.title, url: .deepLink}'
# Browse by craft
curl -s -X POST https://framethrower.ai/api/v1/browse \
-H "Authorization: Bearer ft_YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"shot_type": "close-up", "lens_character": "anamorphic", "limit": 5}' \
| jq '.data | length'
# Autocomplete
curl -s "https://framethrower.ai/api/v1/suggest?q=nolan" \
-H "Authorization: Bearer ft_YOUR_TOKEN" \
| jq '.data.films[].title'Python
import requests
TOKEN = "ft_YOUR_TOKEN"
H = {"Authorization": f"Bearer {TOKEN}"}
# Search by concept
r = requests.post(f"https://framethrower.ai/api/v1/search", headers=H,
json={"query": "anamorphic close-up blue hour", "limit": 5})
for f in r.json()["data"]:
print(f'{f["film"]["title"]} — {f["deepLink"]}')
# Find by color
r = requests.post(f"https://framethrower.ai/api/v1/search/color", headers=H,
json={"colors": ["#c45a28", "#1a1a2e"]})
print(f'{len(r.json()["data"])} frames match that palette')
# Browse craft
r = requests.post(f"https://framethrower.ai/api/v1/browse", headers=H,
json={"director": "Wong Kar-wai", "time_of_day": "night"})
for f in r.json()["data"]:
print(f'{f["film"]["title"]} — {f["metadata"]["lensCharacter"]}')JavaScript / TypeScript
const TOKEN = "ft_YOUR_TOKEN";
const api = (path, body) =>
fetch(`https://framethrower.ai/api/v1${path}`, {
method: body ? "POST" : "GET",
headers: { "Authorization": `Bearer ${TOKEN}`, "Content-Type": "application/json" },
body: body ? JSON.stringify(body) : undefined,
}).then(r => r.json());
// Script → visual references workflow
async function findRefsForScene(sceneDescription) {
// 1. Search by scene text
const { data: results } = await api("/search", {
query: sceneDescription, limit: 10
});
// 2. Pick the best match, find more like it
if (results.length > 0) {
const { data: similar } = await api("/similar", {
frameId: results[0].id, mode: "visual", limit: 5
});
return [...results.slice(0, 5), ...similar];
}
return results;
}
// Use it
const refs = await findRefsForScene(
"candlelit dinner party in a grand ballroom, wide shot, warm"
);
refs.forEach(f => console.log(f.film.title, f.thumbUrl));Response Format
Every endpoint returns JSON with this shape:
{
"data": [ ... ] or { ... }, // the result(s)
"meta": { // context about the request
"total": 20,
"query": "...",
"mode": "hybrid",
...
}
}Frames always include: id, imageUrl (full-size original), thumbUrl (1280px WebP thumbnail), deepLink (opens on FrameThrower), film (title, year, director, dp, genres), metadata (scene description, shot type, camera angle, lens, lighting, moods, colors, etc.). Frame detail also includes prompt — a composed AI image prompt.
Errors return { "error": "message" } with the appropriate HTTP status (400, 401, 403, 404, 500).
Legal
The API surfaces frames as reference material — metadata, thumbnail URLs, and deep links back to FrameThrower. It never returns raw image bytes.
By using the API you agree to the Terms of Service and Intended Use Policy. Bulk redistribution and automated scraping are prohibited. Rights to the original films remain with their respective rights holders.
Questions? contact@framethrower.ai
FrameThrower API v1 · 11 endpoints · No rate limits during preview.