Cinema showtimes API
The cinema showtimes API is GET /3/movie/{movie_id}/showtimes?country=US. It returns cinemas with address and time zone, and each screening with start time, formats and booking link where known. Without country you get per-country counts only. Coverage varies by title, and an empty results array means nothing is known.
Get showtimes for a movie
GET /3/movie/{movie_id}/showtimes?country=US returns the cinemas that screen one movie in one country, each with a list of screenings. country is a 2 letter code. Without it, results stays empty and you get only per-country counts. Coverage varies by country and title, and an empty results array means nothing is known for that pair.
You get the cinema name, chain, address and time zone, and for each screening the start time, auditorium, formats, tags and a booking link where known. Only screenings from today on are returned. The reply describes screenings. It is not a ticketing service.
What data you get
| Endpoint | Returns |
|---|---|
GET /3/movie/{movie_id}/showtimes | Cinemas and screenings of one movie in country, or counts per country without it |
GET /3/movie/now_playing | Movies currently in cinemas, narrowed by region |
GET /3/movie/{movie_id} with append_to_response=showtimes | Details plus showtimes in one request, see showtimes |
Fields in the showtimes reply:
| Field | Type | Meaning |
|---|---|---|
id | integer | Movie id |
country | string or null | The 2 letter code you asked for, null when none was valid |
results | array | One item per cinema, empty when nothing is known or country is missing |
countries | array | Per-country counts: country, name, venues, cities, showtimes, first_day, last_day |
results[].id, name, city, address | integer, strings | Cinema id, name, city and street address |
results[].chain | object or null | key and name of the cinema chain |
results[].timezone | string or null | IANA zone of the cinema, for example Europe/Moscow |
results[].latitude, longitude | number or null | Position, when known |
results[].region, postal_code, phone, url | string or null | Further cinema details, often null |
results[].showtimes | array | Screenings at that cinema |
showtimes[].date | string | Local day such as 2026-10-18 |
showtimes[].start | string | Local start time such as 2026-10-18T21:40, with no offset |
showtimes[].auditorium | string or null | Hall name or number |
showtimes[].formats | array | Screening formats, for example 2D, IMAX or Dolby Atmos |
showtimes[].tags | array | Extra labels such as Reserved Seating |
showtimes[].booking_url | string or null | Link to buy a ticket, when known |
showtimes[].sold_out | boolean | true when the source marks the screening as sold out |
showtimes[].end, audio, subtitles, language, price, currency, prices | various, often null | Filled only when the cinema source provides them |
A reply holds at most 1,500 screenings, ordered by cinema and then start time.
Start in 3 steps
- Open pricing and choose a plan. Showtimes are included in every plan.
- Create a key in your account dashboard.
- Request
/3/movie/{movie_id}/showtimeswith acountrycode, and pass the key inapi_keyor as a Bearer header.
Example request
The bash sample reads showtimes for Fight Club (id 550) in Russia, where amodb has screenings for it today. The JS sample takes the first five movies of the Russian now_playing list and prints up to three screenings per cinema, or a note when none are known.
curl -s "https://api.amodb.dev/3/movie/550/showtimes?country=RU" \
-H "Authorization: Bearer $AMODB_KEY"const BASE = 'https://api.amodb.dev/3';
const headers = { Authorization: `Bearer ${process.env.AMODB_KEY}` };
async function get(path, params = {}) {
const res = await fetch(`${BASE}${path}?${new URLSearchParams(params)}`, { headers });
if (!res.ok) throw new Error(`amodb returned ${res.status} for ${path}`);
return res.json();
}
const country = 'RU';
const playing = await get('/movie/now_playing', { region: country, page: 1 });
for (const movie of playing.results.slice(0, 5)) {
const { results } = await get(`/movie/${movie.id}/showtimes`, { country });
if (results.length === 0) {
console.log(`${movie.title}: no showtimes known`);
continue;
}
for (const cinema of results) {
const times = cinema.showtimes
.slice(0, 3)
.map((s) => `${s.start.slice(5, 10)} ${s.start.slice(11, 16)} ${s.formats.join('/')}`)
.join(', ');
console.log(`${movie.title} at ${cinema.name}, ${cinema.city}: ${times}`);
}
}Trimmed response for country=RU: the first cinema with 2 of its screenings.
{
"id": 550,
"country": "RU",
"results": [
{
"id": 1114,
"name": "Мираж Синема НА БОЛЬШОМ",
"chain": {
"key": "mirage-ru",
"name": "Мираж Синема"
},
"city": "Санкт-Петербург",
"region": null,
"address": "Большой пр. П.С., д. 35А",
"postal_code": null,
"country": "RU",
"timezone": "Europe/Moscow",
"latitude": null,
"longitude": null,
"phone": null,
"url": "https://www.mirage.ru/spb/cinema/1/",
"showtimes": [
{
"date": "2026-10-18",
"start": "2026-10-18T21:40",
"end": null,
"auditorium": null,
"formats": [
"2D"
],
"tags": [],
"audio": null,
"subtitles": null,
"language": null,
"price": null,
"currency": null,
"prices": null,
"booking_url": "https://www.mirage.ru/ticket_new/aca7b114-d587-4fc5-9df6-28568e8fa9b3/",
"sold_out": false
},
{
"date": "2026-10-19",
"start": "2026-10-19T22:20",
"end": null,
"auditorium": "Зал №4",
"formats": [
"2D"
],
"tags": [],
"audio": null,
"subtitles": null,
"language": null,
"price": null,
"currency": null,
"prices": null,
"booking_url": "https://www.mirage.ru/ticket_new/0c32e190-890a-4c81-a754-3300fefc4d5e/",
"sold_out": false
}
]
}
],
"countries": [
{
"country": "RU",
"name": "Russia",
"venues": 2,
"cities": 1,
"showtimes": 7,
"first_day": "2026-10-18",
"last_day": "2026-10-21"
}
]
}Coverage and empty results
Cinema data is not available for every country or title. Plan your interface around that.
| Situation | What you see | What to do |
|---|---|---|
| Screenings known | results has one item per cinema | Show the list |
| Nothing known for this country and title | results is an empty array, countries lists where data exists | Show a neutral note, not an empty table |
No country sent | results is empty, country is null, countries has counts | Let the user pick from countries |
| Unknown movie id | 404 with status_code 34 | Check the id |
| Over your rate | 429 with status_code 25 | Wait for the Retry-After seconds |
An empty array is not an error and not a claim that the movie is missing from cinemas. It means no screening data is known. See errors for the full body format.
Build a listings page for current releases
Combine two endpoints. The list tells you which movies are current, and showtimes fill in the screenings.
| Step | Request | Notes |
|---|---|---|
| 1 | GET /3/movie/now_playing?region=US&page=1 | Up to 20 movies per page, cached for 30 minutes |
| 2 | GET /3/movie/{movie_id}/showtimes?country=US | One call per movie, cached for 30 minutes |
| 3 | Filter in your code | By city, formats or tags |
One page of 20 movies costs 21 requests. A reply for a big release can be several hundred kilobytes, because it holds up to 1,500 screenings. On the 20 requests per minute plan that is a full minute of budget, so fetch in a background job and serve visitors from your stored copy. The 40 and 120 requests per minute plans fit the same job with room to spare. See rate limits for the window and the headers, and trending and lists for the other list endpoints.
Keep your copy fresh
Showtimes change by the day, unlike movie details. Store each reply with its movie id, country and fetch time. A TTL of 30 minutes up to a few hours works for most listings pages, and screenings that already started can be hidden by comparing start with the current time in the cinema's timezone. Because start has no offset, do not shift it into the visitor's time zone.
How it compares
| Capability | Scrape cinema websites | Metadata API without showtimes | amodb |
|---|---|---|---|
| Setup | One scraper per cinema site | Not available | One endpoint, one JSON shape |
| Match to a movie id | Match by title text | Not available | Movie id in the path |
| Coverage | Whatever you can scrape | None | Varies by country and title, empty array when unknown |
| Formats and booking | Parse labels and links | Not available | formats, tags and booking_url fields |
| Upkeep | Breaks when a site changes | None | One JSON shape for every country |
Pricing
Prepaid plans run for 1, 3, 6, 12 or 24 months, with 0, 10, 20, 30 or 40 percent off for longer ones. Nothing renews automatically. The plans allow 20, 40 and 120 requests per minute and each includes showtimes along with all other data. A listings page that refreshes every 30 minutes for a few countries fits the smallest rate. There is no free tier. Choose a plan on pricing.
Questions and answers
How do I get showtimes for a movie?
Send GET /3/movie/{movie_id}/showtimes?country=US with your key. The country parameter is a 2 letter code, and region works as an alias. The reply lists cinemas, and each cinema has its screenings with start time, formats, tags and booking link where known.
What does an empty results array mean?
It means amodb has no screening data for that movie in that country. It is not an error, and it does not say the movie is absent from cinemas. The countries array in the same reply still lists where data exists, so you can offer another country.
Which countries are covered?
Coverage varies by country and title. Every reply holds a countries array with venue, city and showtime counts, up to 60 countries with the most showtimes first. Read it per movie instead of hard coding a list.
Can I list the movies that are in cinemas right now?
Yes. GET /3/movie/now_playing with the region parameter lists current releases, cached for 30 minutes. Take each movie id from that list and request its showtimes with the same country code.
What time zone do start values use?
A start value looks like 2026-10-18T21:40 and carries no UTC offset. Treat it as local wall-clock time at the cinema. Each venue also has a timezone such as Europe/Moscow. Do not convert start into the time zone of the viewer.