# BookMyShow Scraper - Movies, Events & Showtimes (`abotapi/bookmyshow-scraper`) Actor

Scrape BookMyShow movies and live events by city, category or URL. Extract genres, languages, posters, synopsis, cast, show dates and cinema showtimes. Includes incremental monitoring, resume support and MCP export.

- **URL**: https://apify.com/abotapi/bookmyshow-scraper.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Features:** Limited permissions
- **Stats:** 6 total users, 3 monthly users, 98.9% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 movie, event or showtime records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## BookMyShow Scraper: Movies, Events & Showtimes

BookMyShow Scraper turns BookMyShow India into a clean movies-and-events data feed. Get movie listings with cast, genres, languages and formats, live events such as concerts, comedy shows and plays with venue and pricing, and per-cinema showtimes for any city. Search a city and category, or paste exact links, then export to JSON, CSV or Excel, or pull the results straight into your app through the API.

### Why This Scraper?

- **Three ways to find data.** Search a city and category listing, paste exact BookMyShow links (movie pages, event pages, per-day showtimes pages or city explore links), or read the showings of chosen movies over a window of dates.
- **Three record kinds in one dataset.** Movies, live events (concerts, comedy, workshops, plays, sports, activities) and per-cinema showtimes, discriminated by `kind`.
- **Movie filters on the source's own codes.** Language, genre and format narrow a search server-side; unknown codes are dropped instead of silently riding along.
- **Detail enrichment on demand.** Merge each listing row's synopsis, cast, director, formats and release date from its own page, with a small surcharge only on rows actually read.
- **Built for monitoring.** Incremental mode returns only new, updated and reappeared records on repeat runs, and unchanged records are never billed by default.
- **Resume support.** Continue a large pull without paying twice for records already collected.
- **A refused run fails loudly** instead of coming back as an empty, silent success.

### Use Cases

- **Cinema listing apps:** feed movie showtimes, formats and availability for one or more cities into your own booking or discovery app.
- **Event discovery and ticketing tools:** track concerts, comedy shows, plays and sports events with venue, date, price and availability.
- **Entertainment content and media teams:** generate city guides, "what's on" roundups and movie previews automatically.
- **Market research:** monitor movie release patterns, formats and language mixes across Indian cities over time.
- **Price and availability tracking:** watch showtime availability status for specific movies or events on a schedule.

### Data You Get

> Sample shape: values are illustrative placeholders, not from a live record.

| Field | Example |
| --- | --- |
| `kind` | `"movie"` (also `"event"`, `"showtime"`) |
| `recordId` | `"movie:ET00000001"` |
| `eventCode` | `"ET00000001"` |
| `title` | `"Sample Movie Title"` |
| `url` | BookMyShow link to the movie, event or showtimes page |
| `posterUrl` | poster image link (churns hourly; excluded from change detection) |
| `languages` / `genres` | `["hindi", "english"]` / `["drama", "action"]` (movies) |
| `category` | `"movies"` (also `"events"`, `"plays"`, `"sports"`, `"activities"`, `"showtimes"`) |
| `regionCode` | `"SAMPLE"` |
| `venueName` / `venueCode` | `"Sample Cinema"` / `"SAMP"` (events and showtimes) |
| `listingSection` | the widget group title when a listing names it (the live listings currently serve unnamed groups, so it is null; excluded from change detection and not a table column) |
| `tags` | `["2D", "UA"]` |
| `synopsis` | plot or event description (detail pages) |
| `duration` / `releaseDate` | `"2h 15min"` / `"2026-01-01"` (movies, detail pages) |
| `censor` | `"UA"` (movies, detail pages) |
| `formats` | `["2D", "IMAX 2D"]` (movies, detail pages) |
| `cast` / `director` | `["Sample Actor"]` / `"Sample Director"` (movies, detail pages) |
| `rating` / `ratingText` / `ratingCount` | `8.7` / `"8.7/10"` / `166357` (released movies, detail pages; empty until a movie has a rating, never a zero; the count only where the page publishes one) |
| `priceDisplay` / `availability` | `"Sample price display"` / `"Sample availability status"` (events, detail pages) |
| `dateText` / `timeText` | `"1 Jan"` / `"7:00 PM"` (events and showtimes) |
| `showDateCode` / `showDateTime` | `"20260101"` / `"202601011900"` (showtimes only) |
| `sessionId` / `availStatus` | `"999999"` / `"1"` (showtimes only) |
| `infoLabels` / `filters` | `["Recliner"]` / `["subtitled"]` (showtimes only) |
| `changeType` | `"NEW"` (also `"UPDATED"`, `"UNCHANGED"`, `"REAPPEARED"`, `"EXPIRED"`; incremental mode) |
| `changedFields` / `firstSeenAt` / `lastSeenAt` | `[]` / ISO timestamp / ISO timestamp (incremental mode) |

Showtime records leave `title`, `languages` and `genres` empty since they represent one showing rather than the movie or event itself; movie and event records do not carry the showtime-only fields (`showDateCode`, `showDateTime`, `sessionId`, `availStatus`, `infoLabels`, `filters`).

#### Showtime price, status and region fields

Showtime rows (one per showing) carry: `sessionKey` (stable id: venue code, session id and show time), `showDateTimeUtc` (the local show time converted to UTC), `showDateCode`, `eventTitle`, `eventLanguage`, `eventFormat`, `eventGenre`, `censorRating`, `venueChain`, `venueUrl`, `citySlug`, `cutOffAtUtc`, `isMTicketAvailable` and `scrapedAt`.

- **Prices:** `priceClasses` lists the seat categories of the showing as `{name, price, availability}` (for example `EXECUTIVE ROWS`, 630, `filling_fast`), read from the price sheet the site itself ships for every showing. `minPrice`, `maxPrice` and `priceClassCount` summarise it and `currency` is `INR`. A showing with no price sheet (some sold-out showings) returns `priceClasses` empty and the three summaries null, never a zero.
- **Status:** `sessionStatus` decodes the site's own `availStatus` code into `available`, `filling_fast`, `almost_full` or `sold_out` (the codes 3, 2, 1 and 0, measured on over a thousand live showings). `sessionAttributes` lists the screen attributes of the showing (for example `Laser`, `Dolby Atmos`, `Insignia`, `Cancellable`) decoded from the `filters` codes.
- **Region:** `regionName`, `regionCode`, `regionSlug` and `subCode` come from the site's own region record for the page (for example `Delhi-NCR`, `NCR`, `ncr` and, for a sub-region such as Noida, `NOIDA`).
- **Seat layout:** `seatLayoutUrl` is the site's own seat-selection page for the showing. Seat counts and a full-layout flag are only served behind that page's sign-in (measured 2026-11-09), so the actor has no seat-count or full-layout fields at all and never returns them as empty values; the availability label per price class is the public signal.

**Date handling in URL mode:** a showtimes link with a date code (`.../buytickets/ET00496545/20261110`) returns that day; a link without a date returns the site's current day. A date in the past falls back to the current showings with a warning in the run log. One showtimes link is one day; to cover several days use showtimes mode below.

#### Showtimes mode: movies and dates

Set **Mode** to showings by movie and date to get every showing of the movies you choose over a window of days, without pasting one link per day:

- **Movies:** list movie codes in `eventCodes` (up to 25), or leave it empty to read the top movies of the city's Now Showing listing (`maxMovies`, 1 to 25, default 3).
- **Dates:** `dateMode` is `AUTO_DISCOVER` (today and up to `maxDaysAhead` days after, 1 to 14, default 3; a movie stops after `emptyDateStreakLimit` empty days in a row, 1 to 7, default 2), `EXPLICIT_DATES` (the `dates` you list, up to 14) or `DATE_RANGE` (`fromDate` to `toDate` inclusive, capped at 14 days). Days are India calendar days, and past days are skipped.
- **Date range details:** an empty or past `fromDate` starts today. With no `toDate` the range is the first day plus the 3 days after it, 4 days in all. A `fromDate` or `toDate` that is not a real calendar date is treated as empty, and a `toDate` before the first day reads nothing and says so in the run log. In `AUTO_DISCOVER` the window is likewise today plus `maxDaysAhead` days after it.
- **City:** a Delhi-NCR sub-region such as `noida` or `gurgaon` reads that sub-region's own showings.
- Every list and window above has a finite cap, `maxItems` still bounds the run, and showtimes mode adds no detail surcharge.

### How to Use

1. Pick a **mode**: `search` (a city and category listing), `url` (paste BookMyShow links) or `showtimes` (the showings of chosen movies over a date window).
2. For search mode, set **City** and **Category**; movies also accept language, genre and format filters. For URL mode, paste the links.
3. Turn **Fetch details** on or off, and set **Max items** to control run size and cost.
4. Click **Start**, then download the dataset as JSON, CSV or Excel, or read it through the API.

**Search movies in a city, filtered by language:**

```json
{
  "mode": "search",
  "city": "mumbai",
  "category": "movies",
  "languages": "hindi,english",
  "maxItems": 20
}
```

**Search live events in another city:**

```json
{
  "mode": "search",
  "city": "bengaluru",
  "category": "events",
  "maxItems": 50
}
```

**Paste links (movie page, city explore link):**

```json
{
  "mode": "url",
  "urls": [
    "https://in.bookmyshow.com/movies/mumbai/sample-movie-title/ET00000001",
    "https://in.bookmyshow.com/explore/movies-pune"
  ],
  "fetchDetails": true
}
```

#### URL mode link shapes

URL mode run with the `urls` field untouched scrapes the 16 example links prefilled in that field, which cover every shape below except the bare-host movie page (accepted, but not in the prefilled list). Links on in.bookmyshow.com and bookmyshow.com are accepted; any other host is skipped with a warning in the run log. A showtimes link with a past date falls back to the current showings, with a warning. A link that yields no records is reported in the log.

| Shape | Example |
| --- | --- |
| City movies explore listing | `https://in.bookmyshow.com/explore/movies-mumbai` |
| City events explore listing | `https://in.bookmyshow.com/explore/events-mumbai` |
| City plays explore listing | `https://in.bookmyshow.com/explore/plays-mumbai` |
| City sports explore listing | `https://in.bookmyshow.com/explore/sports-mumbai` |
| City activities explore listing | `https://in.bookmyshow.com/explore/activities-mumbai` |
| Filtered explore listing (languages) | `https://in.bookmyshow.com/explore/movies-mumbai?languages=hindi` |
| City home explore page | `https://in.bookmyshow.com/explore/home/mumbai` |
| Movie page | `https://in.bookmyshow.com/movies/mumbai/clayface/ET00496545` |
| Movie page, other city path | `https://in.bookmyshow.com/movies/bengaluru/clayface/ET00496545` |
| Upcoming movies explore listing | `https://in.bookmyshow.com/explore/upcoming-movies-mumbai` |
| Live event page, non-numeric code | `https://in.bookmyshow.com/events/amit-kumar-live-in-mulund/et675ifet4` |
| Legacy showtimes page | `https://in.bookmyshow.com/buytickets/clayface-mumbai/movie-mumbai-ET00496545-MT/20261111` |
| City events listing, bare host | `https://www.bookmyshow.com/explore/events-bengaluru` |
| Movie page, bare host | `https://bookmyshow.com/movies/mumbai/clayface/ET00496545` |
| Live event page | `https://in.bookmyshow.com/events/acrylic-painting-workshop/ET00499618` |
| Per-day showtimes page with date code | `https://in.bookmyshow.com/movies/mumbai/clayface/buytickets/ET00496545/20261110` |
| Showtimes page without date | `https://in.bookmyshow.com/movies/mumbai/clayface/buytickets/ET00496545` |

**Incremental monitoring for a scheduled run:**

```json
{
  "mode": "search",
  "city": "chennai",
  "category": "movies",
  "incrementalMode": true,
  "stateKey": "chennai-movies-daily",
  "maxItems": 0
}
```

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/bookmyshow-scraper").call(run_input={"mode": "search", "city": "mumbai", "category": "movies"})
for record in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(record["kind"], record["title"])
```

JavaScript:

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/bookmyshow-scraper').call({ mode: 'search', city: 'mumbai', category: 'movies' });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the **Integrations** tab.

#### How the city listing is read

Each city and category serves its full listing in one page: there is no second page to walk. **Max items** trims how many of that page's records are returned (0 = no limit); it does not reveal more records. To get a different set, change the city, category, or the language, genre and format filters.

#### Resume and recurring updates

- **Resume** (`resumeFromRunId`) continues one interrupted run: paste its run or dataset ID and the actor skips every record id already collected there, so you don't pay twice.
- **Incremental mode** (`incrementalMode`) is for scheduled runs over the same city, category and filters. Each record is classified `NEW`, `UPDATED` (with `changedFields`), `UNCHANGED` (suppressed and not billed unless `emitUnchanged` is on), `REAPPEARED` or `EXPIRED` (only after a run that scanned the whole listing, and only with `emitExpired`). The poster image URL and the listing widget group are excluded from change detection, so neither churning alone produces an UPDATED row. `stateKey` names or shares the stored state; leave it empty to let the actor derive one automatically from the search or link settings. `ignoreFieldsForChanges` lists extra fields (dotted paths for nested values) to leave out of change detection; changing that list never turns stored records into a one-time wave of UPDATED rows. A showing's seat-category availability moves as seats sell, so `priceClasses` shows as changed when a category's label moves (the same real change as `availStatus`); add `priceClasses.availability` to `ignoreFieldsForChanges` to leave it out. With incremental mode off, output is exactly as before.

#### Output views

The dataset has these table views in the Console: **Records** (everything), **Movies**, **Live events**, **Showtimes** and **Changes (incremental)**.

### Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step **after** the scrape: the Apify dataset is never changed.

**What gets written to the connector:** a condensed, human-readable **summary** of each record, not the full JSON. Each item becomes one entry with a **title** and its key fields flattened to plain text. The **complete record always stays in the Apify dataset**.

1. Authorize a connector once under **Apify, Settings, Integrations** (Notion, Linear, Airtable, or Apify).
2. Select it in the **"Pipe results into your apps"** input field. (If the picker is empty, you haven't authorized a connector yet.)
3. For **Notion**, also set `notionParentPageUrl` to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

### Input Parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `mode` | string | `search` | `search` (city and category listing), `url` (paste BookMyShow links) or `showtimes` (showings by movie and date). |
| `city` | string | `mumbai` | Search mode: the city slug, for example `mumbai`, `national-capital-region-ncr`, `bengaluru`, `hyderabad`, `chandigarh`, `ahmedabad`, `pune`, `chennai`, `kolkata`, `kochi`. Any other valid city slug from the site works. |
| `category` | string | `movies` | Search mode listing: `movies`, `events`, `plays`, `sports`, or `activities`. |
| `languages` | string | (none) | Movies only: comma-separated language codes, for example `hindi, english, tamil`. Unknown codes are dropped rather than silently ignored. |
| `genres` | string | (none) | Movies only: comma-separated genre codes, for example `action, drama, comedy`. Unknown codes are dropped rather than silently ignored. |
| `formats` | string | (none) | Movies only: comma-separated format codes, for example `2d, 3d, 4dx, imax-2d`. Unknown codes are dropped rather than silently ignored. |
| `urls` | array | one example of each link shape | URL mode: BookMyShow pages to read, one per line. Movie pages and live-show pages are one record each; per-day showtimes pages are one record per showing; city explore links are walked like search mode. |
| `eventCodes` | array | (none) | Showtimes mode: up to 25 BookMyShow codes in any letter case: ET plus digits (movies), or the site's non-numeric form of ET plus 8 letters or digits; a full BookMyShow link containing a code also works. Showings are read from the movie showtimes pages, so use movie codes. Empty uses the city's top movies. |
| `maxMovies` | integer | `3` | Showtimes mode with no movie codes: how many Now Showing movies to read, 1 to 25. |
| `dateMode` | string | `AUTO_DISCOVER` | Showtimes mode: `AUTO_DISCOVER`, `EXPLICIT_DATES` or `DATE_RANGE`. |
| `dates` | array | (none) | Explicit dates mode: `YYYY-MM-DD` dates, up to 14. Past dates are skipped. |
| `fromDate` | string | (none) | Date range mode: first day, `YYYY-MM-DD`. Empty or past starts today. |
| `toDate` | string | (none) | Date range mode: last day, `YYYY-MM-DD`, inclusive; the range is capped at 14 days. Empty reads the first day plus the 3 days after it (4 days). |
| `maxDaysAhead` | integer | `3` | Auto discover: days after today to read at most, 1 to 14. |
| `emptyDateStreakLimit` | integer | `2` | Auto discover: stop a movie after this many empty days in a row, 1 to 7. |
| `maxItems` | integer | `20` | Stop after this many records (`0` = no limit; the run then stops when the results run out). |
| `maxPages` | integer | `0` | Upper bound on pages walked per scope. This listing surface arrives in one server-rendered page, so a walk reads exactly that page; the bound exists for consistency and defaults wide open. |
| `fetchDetails` | boolean | `true` | Read each listing row's own page and merge the richer fields (synopsis, duration, censor, release date, formats, cast, director, and for live shows date, time, venue, price display and availability). Adds a per-row surcharge only on rows actually read; refused reads are pushed without the extra fields and never charged. |
| `resumeFromRunId` | string | (none) | Continue one interrupted run: paste a previous run ID or dataset ID. |
| `incrementalMode` | boolean | `false` | Turn on for daily or recurring monitoring. Returns only new and changed records on repeat runs over the same scope. |
| `stateKey` | string | (none) | Optional. Name this monitoring campaign to keep its state stable, or deliberately share state across differently configured runs. Leave empty to derive a key automatically from the search and link settings. |
| `emitUnchanged` | boolean | `false` | Also return (and bill) records that have not changed since the last run. |
| `emitExpired` | boolean | `false` | Also return (and bill) records that were present before but are no longer found. Only produced once a run has fully scanned the tracked search. |
| `ignoreFieldsForChanges` | array | (none) | Incremental mode only: field names that must not count as a change. Dotted paths reach nested values (for example `showtimes.availability`). Returned records still carry the live values. |
| `mcpConnectors` | array | (none) | Optional: send a summary of each record to apps you authorized under Integrations. |
| `notionParentPageUrl` | string | (none) | Notion connector only: page under which item pages are created. |
| `maxNotifyListings` | integer | `50` | Cap on items written to each connector per run. Does not affect the dataset. |
| `proxyConfiguration` | object | Residential, India | Apify Proxy settings. Every run uses residential India exits by default: the lane the site reliably serves. You can bring your own proxy here. |

### Output Example

> Sample shape: values are illustrative placeholders, not from a live record.

```json
{
  "kind": "movie",
  "recordId": "movie:ET00000001",
  "eventCode": "ET00000001",
  "title": "Sample Movie Title",
  "url": "https://in.bookmyshow.com/movies/sample-city/sample-movie-title/ET00000001",
  "posterUrl": "https://assets-in.bmscdn.com/discovery-catalog/events/sample-poster.jpg",
  "languages": ["hindi", "english"],
  "genres": ["drama", "action"],
  "category": "movies",
  "regionCode": "SAMPLE",
  "venueName": null,
  "venueCode": null,
  "listingSection": "Recommended Movies",
  "tags": ["2D", "UA"],
  "synopsis": "A sample synopsis describing the plot in general terms.",
  "duration": "2h 15min",
  "censor": "UA",
  "releaseDate": "2026-01-01",
  "formats": ["2D", "IMAX 2D"],
  "cast": ["Sample Actor One", "Sample Actor Two"],
  "director": "Sample Director",
  "priceDisplay": null,
  "availability": null,
  "dateText": null,
  "timeText": null
}
```

### Plan Requirement

BookMyShow refuses datacenter connections on every exit: measured, the site answers an "Attention Required" block page (HTTP 403) to the default datacenter pool every time. Residential connections located in India are required, and this actor uses them by default, so a paid Apify plan (or your own residential proxy URLs under **Connection**) is needed. Even on residential exits some fetches meet a short "Just a moment..." check (measured 4 in about 30, roughly one in seven); the actor simply retries on a fresh exit.

Apify free plans do not include residential proxies. On a free plan the run logs this notice and continues on a backup connection, where some pages may still be unavailable:

> The selected connection is unavailable to this run. Apify free plans do not include residential proxies. Continuing on a backup connection; some pages may still be unavailable. For residential access, upgrade at https://apify.com/pricing or supply your own proxy URLs.

If nothing can be read the run fails with a clear message instead of returning an empty dataset: "No results: residential proxies are unavailable on this run (Apify free plans do not include them), and the backup connection could not load the requested BookMyShow pages." (free plan), or "The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required." Setting the environment variable `BOOKMYSHOW_IN_ALTERNATE_CONNECTION=0` turns the backup connection off.

### FAQ

#### How much does it cost?

Billing uses three registered events. `apify-default-dataset-item` is charged once per movie, event or showtime record returned in the dataset. `detail-enrichment` is charged once per row whose own detail page was read and merged (only when Fetch details is on and the read succeeds; refused reads are never charged). `apify-actor-start` is charged once per run, per GB of memory. Unchanged records suppressed in incremental mode are not returned and not billed. The **Pricing** tab shows the current rates. Use **Max items** to cap the cost of any run.

#### Is it legal to scrape BookMyShow?

This actor collects only publicly available listing data. You are responsible for how you use it: follow BookMyShow's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Posters, synopses and other creative assets may be subject to third-party rights.

#### Can I get only new or changed listings on a schedule?

Yes. Schedule the actor from the **Schedules** tab and turn on **Incremental mode**. Each run then returns only new, updated and reappeared records for the same city, category and filters, and unchanged ones are not billed by default.

#### Why did a run return fewer records than expected?

Each city and category listing serves its full page in one response; there is no second page to walk. **Max items** trims how many of that page's records come back, it does not reveal more. If you expected more, check the spelling of the city slug, clear the language, genre or format filters, or raise Max items.

#### Why did my run fail instead of returning an empty dataset?

If every request to the site is refused, the run stops with a clear message so "this city has nothing on today" is never confused with "nothing could be read". Run it again in a few minutes. If only some links or scopes could be read, you still get what was found.

#### Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

### 🔗 Want more sports data?

Pair this actor with these related scrapers from the same team:

<table>
<tr><td>⚽ <a href="https://apify.com/abotapi/hotstar-com-scraper"><b>JioHotstar Scraper</b></a><br>Scrape the JioHotstar catalog by content type or URL. Extract shows, movies, episodes...</td><td>⚽ <a href="https://apify.com/abotapi/eventim-de-event-scraper"><b>Eventim Scraper</b></a><br>Scrape CTS Eventim Germany and EU event catalogue: concerts, festivals, comedy, sports...</td></tr>
<tr><td>⚽ <a href="https://apify.com/abotapi/sportsbook-odds-scraper"><b>Sportsbook Odds Scraper (1xBet, Melbet, Linebet, Paripulse)</b></a><br>Collect live and prematch betting odds from 1xBet, Melbet, Linebet and Paripulse. Give it...</td><td>⚽ <a href="https://apify.com/abotapi/whatnot-scraper"><b>Whatnot Scraper</b></a><br>Scrape Whatnot live and upcoming shows, queued items and lots, and seller profiles...</td></tr>
<tr><td>⚽ <a href="https://apify.com/abotapi/fanduel-odds-scraper"><b>FanDuel Odds Scraper</b></a><br>Scrape FanDuel sportsbook odds, including moneylines, spreads, totals, player props and...</td><td>⚽ <a href="https://apify.com/abotapi/strava-public-data-scraper"><b>Strava Data Scraper</b></a><br>Scrape public Strava data: clubs (members, location, sport, settings), athlete profiles...</td></tr>
</table>

👉 [Browse all abotapi scrapers](https://apify.com/abotapi)

### 💬 Support

- 🐞 **Found a bug or a missing field?** Open a ticket on the [Issues tab](https://apify.com/abotapi/bookmyshow-scraper/issues/open). We usually reply within hours.
- 🛠️ **Need another site, extra fields or a private build?** Email <contact@abotapi.com>.
- ⭐ **Enjoying it?** A quick review on the actor page helps other users find it.

# Actor input Schema

## `mode` (type: `string`):

Search walks a city and category listing (movies, events, plays, sports, activities). URL mode reads the exact BookMyShow pages you paste. Showtimes mode returns one row per showing (cinema, time, seat-category prices, availability) for the movies and dates you choose.

## `city` (type: `string`):

Search mode: the city slug, for example mumbai, national-capital-region-ncr, bengaluru, hyderabad, chandigarh, ahmedabad, pune, chennai, kolkata, kochi (the top ten on the site). Any other city slug from the site works too.

## `category` (type: `string`):

Search mode: which listing to walk in the city.

## `languages` (type: `string`):

Movies only: comma-separated language codes, for example hindi, english, tamil, telugu, malayalam, marathi, gujarati, punjabi, kannada, assamese, korean. Unknown codes are dropped rather than silently ignored.

## `genres` (type: `string`):

Movies only: comma-separated genre codes, for example action, drama, comedy, thriller, romantic, horror, sci-fi, animation, biography. Unknown codes are dropped rather than silently ignored.

## `formats` (type: `string`):

Movies only: comma-separated format codes, for example 2d, 3d, 4dx, imax-2d, 4dx-3d, epiq, mx4d, ice-3d. Unknown codes are dropped rather than silently ignored.

## `urls` (type: `array`):

URL mode: BookMyShow pages to read, one per line. Movie pages (/movies/...) and live-show pages (/events/...) are one record each; per-day showtimes pages (buytickets links) are one record per showing; city explore links (/explore/...) are walked like search mode. Multi-value supported.

## `eventCodes` (type: `array`):

Showtimes mode: BookMyShow codes in any letter case, one per line, up to 25: ET followed by digits (movies, for example ET00451914) or the site's non-numeric form of ET plus 8 letters or digits; a full BookMyShow link containing a code also works. Showings are read from the movie showtimes pages, so use movie codes. Leave empty to use the top movies of the City's listing (see Movies to read). Ignored in search and URL mode.

## `maxMovies` (type: `integer`):

Showtimes mode with no movie codes: how many movies from the City's Now Showing listing to read, in listing order. 1 to 25.

## `dateMode` (type: `string`):

AUTO_DISCOVER reads today and the following days until the days run out (see Days ahead and Empty-day stop). EXPLICIT_DATES reads exactly the dates you list. DATE_RANGE reads every day from From date to To date inclusive; with no To date it reads the first day plus the 3 days after it (4 days).

## `dates` (type: `array`):

Explicit dates mode: dates as YYYY-MM-DD, one per line, up to 14. Past dates are skipped (the site only serves today onward).

## `fromDate` (type: `string`):

Date range mode: first day, YYYY-MM-DD. Defaults to today when empty or in the past.

## `toDate` (type: `string`):

Date range mode: last day, YYYY-MM-DD, inclusive. The range is capped at 14 days. Empty reads the first day plus the 3 days after it (4 days).

## `maxDaysAhead` (type: `integer`):

Auto discover: how many days after today to read at most. 1 to 14.

## `emptyDateStreakLimit` (type: `integer`):

Auto discover: stop a movie after this many days in a row with no showings. 1 to 7.

## `maxItems` (type: `integer`):

Stop after this many records (0 = no limit; the run then stops when the results run out).

## `maxPages` (type: `integer`):

Upper bound on pages walked per scope. This listing surface arrives in one server-rendered page, so the walk reads exactly that page; the bound exists for consistency and defaults wide open.

## `fetchDetails` (type: `boolean`):

Read each listing row's own page and merge the richer fields: synopsis, duration, censor, release date, formats, cast, director, and for live shows the date, time, venue details, price display and availability. Adds one detail read per returned row (a per-row surcharge applies); rows whose detail page is refused are pushed without the extra fields and never charged. Turn off to return the faster listing-shape rows only.

## `proxyConfiguration` (type: `object`):

Apify Proxy settings. By default every run (Console, API or schedule) uses residential India exits: the lane the site reliably serves (measured). The groupless datacenter pool is refused on roughly half its exits.

## `resumeFromRunId` (type: `string`):

Paste a previous run ID or dataset ID to continue a large pull without returning records already collected there.

## `incrementalMode` (type: `boolean`):

Turn this on for daily or recurring monitoring. The first run returns every matching record as NEW. Later runs normally return only NEW, UPDATED and REAPPEARED records. The poster image URL is excluded from change detection (it embeds a live like-count), so a poster churn alone is not an UPDATED row. Turn on Emit unchanged or Emit expired only when you also want those rows returned (and billed).

## `stateKey` (type: `string`):

Optional. Name this monitoring campaign to keep its state stable, or deliberately share state across differently configured runs. Leave empty to let the actor derive a key automatically from the search and link settings.

## `emitUnchanged` (type: `boolean`):

Off by default. Turn on to also return records that have not changed since the last run, marked UNCHANGED. This returns, and bills, extra rows you already have.

## `emitExpired` (type: `boolean`):

Off by default. Turn on to also return records that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search.

## `ignoreFieldsForChanges` (type: `array`):

Field names that must not count as a change in incremental mode, one per entry. Use dotted paths for nested values (for example showtimes.availability). A record whose only differences are in these fields stays UNCHANGED. The returned records still carry the live values. Leave empty to track every field.

## `mcpConnectors` (type: `array`):

Optionally send results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize one under Apify, Settings, API & Integrations, then select it here. Notion gets a rich page-per-item export; other connectors get a best-effort write or digest. Leave empty to skip; never changes the dataset output.

## `notionParentPageUrl` (type: `string`):

URL or id of the Notion page under which item pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on items written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "city": "mumbai",
  "category": "movies",
  "urls": [
    "https://in.bookmyshow.com/explore/movies-mumbai",
    "https://in.bookmyshow.com/explore/events-mumbai",
    "https://in.bookmyshow.com/explore/plays-mumbai",
    "https://in.bookmyshow.com/explore/sports-mumbai",
    "https://in.bookmyshow.com/explore/activities-mumbai",
    "https://in.bookmyshow.com/explore/movies-mumbai?languages=hindi",
    "https://in.bookmyshow.com/explore/home/mumbai",
    "https://in.bookmyshow.com/movies/mumbai/clayface/ET00496545",
    "https://in.bookmyshow.com/movies/bengaluru/clayface/ET00496545",
    "https://in.bookmyshow.com/explore/upcoming-movies-mumbai",
    "https://in.bookmyshow.com/events/acrylic-painting-workshop/ET00499618",
    "https://in.bookmyshow.com/movies/mumbai/clayface/buytickets/ET00496545/20261110",
    "https://in.bookmyshow.com/movies/mumbai/clayface/buytickets/ET00496545",
    "https://in.bookmyshow.com/events/amit-kumar-live-in-mulund/et675ifet4",
    "https://in.bookmyshow.com/buytickets/clayface-mumbai/movie-mumbai-ET00496545-MT/20261111",
    "https://www.bookmyshow.com/explore/events-bengaluru"
  ],
  "eventCodes": [],
  "maxMovies": 3,
  "dateMode": "AUTO_DISCOVER",
  "dates": [],
  "maxDaysAhead": 3,
  "emptyDateStreakLimit": 2,
  "maxItems": 20,
  "maxPages": 0,
  "fetchDetails": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "IN"
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "ignoreFieldsForChanges": [],
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `movies` (type: `string`):

No description

## `events` (type: `string`):

No description

## `showtimes` (type: `string`):

No description

## `changes` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "mode": "search",
    "city": "mumbai",
    "category": "movies",
    "urls": [
        "https://in.bookmyshow.com/explore/movies-mumbai",
        "https://in.bookmyshow.com/explore/events-mumbai",
        "https://in.bookmyshow.com/explore/plays-mumbai",
        "https://in.bookmyshow.com/explore/sports-mumbai",
        "https://in.bookmyshow.com/explore/activities-mumbai",
        "https://in.bookmyshow.com/explore/movies-mumbai?languages=hindi",
        "https://in.bookmyshow.com/explore/home/mumbai",
        "https://in.bookmyshow.com/movies/mumbai/clayface/ET00496545",
        "https://in.bookmyshow.com/movies/bengaluru/clayface/ET00496545",
        "https://in.bookmyshow.com/explore/upcoming-movies-mumbai",
        "https://in.bookmyshow.com/events/acrylic-painting-workshop/ET00499618",
        "https://in.bookmyshow.com/movies/mumbai/clayface/buytickets/ET00496545/20261110",
        "https://in.bookmyshow.com/movies/mumbai/clayface/buytickets/ET00496545",
        "https://in.bookmyshow.com/events/amit-kumar-live-in-mulund/et675ifet4",
        "https://in.bookmyshow.com/buytickets/clayface-mumbai/movie-mumbai-ET00496545-MT/20261111",
        "https://www.bookmyshow.com/explore/events-bengaluru"
    ],
    "eventCodes": [],
    "maxMovies": 3,
    "dateMode": "AUTO_DISCOVER",
    "dates": [],
    "maxDaysAhead": 3,
    "emptyDateStreakLimit": 2,
    "maxItems": 20,
    "maxPages": 0,
    "fetchDetails": true,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "IN"
    },
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false,
    "ignoreFieldsForChanges": [],
    "maxNotifyListings": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/bookmyshow-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "mode": "search",
    "city": "mumbai",
    "category": "movies",
    "urls": [
        "https://in.bookmyshow.com/explore/movies-mumbai",
        "https://in.bookmyshow.com/explore/events-mumbai",
        "https://in.bookmyshow.com/explore/plays-mumbai",
        "https://in.bookmyshow.com/explore/sports-mumbai",
        "https://in.bookmyshow.com/explore/activities-mumbai",
        "https://in.bookmyshow.com/explore/movies-mumbai?languages=hindi",
        "https://in.bookmyshow.com/explore/home/mumbai",
        "https://in.bookmyshow.com/movies/mumbai/clayface/ET00496545",
        "https://in.bookmyshow.com/movies/bengaluru/clayface/ET00496545",
        "https://in.bookmyshow.com/explore/upcoming-movies-mumbai",
        "https://in.bookmyshow.com/events/acrylic-painting-workshop/ET00499618",
        "https://in.bookmyshow.com/movies/mumbai/clayface/buytickets/ET00496545/20261110",
        "https://in.bookmyshow.com/movies/mumbai/clayface/buytickets/ET00496545",
        "https://in.bookmyshow.com/events/amit-kumar-live-in-mulund/et675ifet4",
        "https://in.bookmyshow.com/buytickets/clayface-mumbai/movie-mumbai-ET00496545-MT/20261111",
        "https://www.bookmyshow.com/explore/events-bengaluru",
    ],
    "eventCodes": [],
    "maxMovies": 3,
    "dateMode": "AUTO_DISCOVER",
    "dates": [],
    "maxDaysAhead": 3,
    "emptyDateStreakLimit": 2,
    "maxItems": 20,
    "maxPages": 0,
    "fetchDetails": True,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "IN",
    },
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
    "ignoreFieldsForChanges": [],
    "maxNotifyListings": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/bookmyshow-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "mode": "search",
  "city": "mumbai",
  "category": "movies",
  "urls": [
    "https://in.bookmyshow.com/explore/movies-mumbai",
    "https://in.bookmyshow.com/explore/events-mumbai",
    "https://in.bookmyshow.com/explore/plays-mumbai",
    "https://in.bookmyshow.com/explore/sports-mumbai",
    "https://in.bookmyshow.com/explore/activities-mumbai",
    "https://in.bookmyshow.com/explore/movies-mumbai?languages=hindi",
    "https://in.bookmyshow.com/explore/home/mumbai",
    "https://in.bookmyshow.com/movies/mumbai/clayface/ET00496545",
    "https://in.bookmyshow.com/movies/bengaluru/clayface/ET00496545",
    "https://in.bookmyshow.com/explore/upcoming-movies-mumbai",
    "https://in.bookmyshow.com/events/acrylic-painting-workshop/ET00499618",
    "https://in.bookmyshow.com/movies/mumbai/clayface/buytickets/ET00496545/20261110",
    "https://in.bookmyshow.com/movies/mumbai/clayface/buytickets/ET00496545",
    "https://in.bookmyshow.com/events/amit-kumar-live-in-mulund/et675ifet4",
    "https://in.bookmyshow.com/buytickets/clayface-mumbai/movie-mumbai-ET00496545-MT/20261111",
    "https://www.bookmyshow.com/explore/events-bengaluru"
  ],
  "eventCodes": [],
  "maxMovies": 3,
  "dateMode": "AUTO_DISCOVER",
  "dates": [],
  "maxDaysAhead": 3,
  "emptyDateStreakLimit": 2,
  "maxItems": 20,
  "maxPages": 0,
  "fetchDetails": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "IN"
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "ignoreFieldsForChanges": [],
  "maxNotifyListings": 50
}' |
apify call abotapi/bookmyshow-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/bookmyshow-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/RcctTn0tH6RKbiTbp/builds/DJpS57jpo7YzZQIOq/openapi.json
