# Playbill Scraper (`crawlerbros/playbill-scraper`) Actor

Scrape Playbill's Broadway database - search shows, people and venues, browse by theatre, and fetch full show detail pages with cast, creative team, opening/closing dates and synopses.

- **URL**: https://apify.com/crawlerbros/playbill-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** Automation, Developer tools, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Playbill Scraper

Scrape [Playbill.com](https://www.playbill.com/) — the trusted theatre resource since 1884 — covering Broadway, Off-Broadway, National Tours and London shows. Search the full Playbill database of 28,000+ shows, 148,000+ people and 2,700+ venues; browse everything a theatre has staged; or pull full production detail pages with cast, creative team, opening/closing dates and synopses. No login, no cookies — free-plan friendly.

### What this actor does

- **Three modes:** `search`, `browseByVenue`, `byUrl`
- **Search sections:** Shows (default), People, Venues
- **Genre filter:** Broadway, Off-Broadway, Tour (National Tours), London
- **Sort options:** Relevance or Closing Date (most recently closed first, via Playbill's date replica index)
- **Full show metadata:** venue + city/state, address, first preview / opening / closing dates, running time, showtimes, teaser, synopsis, schedule notes, creative credits, show categories, buy-tickets link, popularity views (total / month / week / today)
- **byUrl:** production pages (full cast + creative team), person pages (credits with roles), venue pages (production history)
- **Optional enrichment:** `includeCast` attaches cast lists and creative credits to search results
- **Empty fields are omitted** — every record carries `sourceUrl`, `scrapedAt`, `recordType`

### Output fields

#### Shows (`recordType: "show"`)

- `showId`, `uid`, `title`, `akaName`
- `genre`, `genreTags[]` (e.g. `Broadway`, `Musical`, `Original`)
- `venueName`, `venueAddress`, `venueCity`, `venueState`, `venueType`
- `previewDate`, `openDate`, `closeDate` — `YYYY-MM-DD`
- `runTime`, `showtimes`, `teaser`, `synopsis` / `description`, `notes` (schedule notes)
- `creators[]` (e.g. `Stephen Schwartz`), `credits{}` (lyrics / music / book / …)
- `showCategories[]` (e.g. `Play`, `Musical`), `isTour`, `openingYear`, `precedes1920`
- `buyTicketsLink`, `cast[]` — name, role, person link (with `includeCast` / `byUrl`)
- `viewsTotal`, `viewsMonth`, `viewsWeek`, `viewsToday`, `thumbnailUrl`, `coverUrl`
- `productionUid` (byUrl), `sourceUrl`

#### People (`recordType: "person"`)

- `personId`, `fullName`, `firstName`, `lastName`, `aka`
- `professions[]` (e.g. `Performer`, `Writer`, `Producer`), `organizations[]`
- `gender`, `birth`, `death`, `placeOfBirth`, `placeOfDeath`, `bornText`
- `bio`, `inRunningShow`, `inRunningShowUntil`, `starPerformerIn`, `starPerformerUntil`
- `showRoleCount`, `starShowRoleCount`, `hasShowRoles`, `isOrganization`, `isUniverse`
- `credits[]` — productions with role and opening date (byUrl)
- `thumbnailUrl`, `sourceUrl`

#### Venues (`recordType: "venue"`)

- `venueId`, `venueName`, `venueAddress`, `venueCity`, `venueState`, `year`
- `website`, `stageDoorInfo`, `bathrooms`, `waterFountain`
- `viewsTotal`, `viewsThisWeek`, `viewsThisMonth`
- `venueFacts{}` — longest-running show, performance counts (byUrl)
- `productions[]` — production history (byUrl)
- `sourceUrl`

Every record also includes `scrapedAt` (UTC ISO timestamp) and `recordType`.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | enum | `search` | `search` / `browseByVenue` / `byUrl` |
| `searchQuery` | string | `wicked` | Free-text query (mode=search) |
| `searchSection` | enum | `shows` | `shows` / `people` / `venues` |
| `sortBy` | enum | `relevance` | `relevance` / `closingDate` (most recent close first) |
| `venueName` | string | `Gershwin Theatre` | Theatre to browse (mode=browseByVenue) |
| `urls` | array | – | Production / person / venue URLs (mode=byUrl) |
| `genre` | enum | `broadway` | `broadway` / `offbroadway` / `touring` / `london` |
| `containsKeyword` | string | – | Client-side title/synopsis substring filter |
| `dateRangeFrom` / `dateRangeTo` | string | – | Show window (`YYYY-MM-DD`) — opening/closing overlap |
| `includeCast` | bool | `false` | Enrich shows with cast & creative credits |
| `maxItems` | int | `50` | Hard cap (1–1000) |
| `proxyConfiguration` | object | off | Optional Apify proxy (auto-engaged on 403/429) |

#### Examples

**Broadway musicals opening in 2024:**

```json
{
  "mode": "search",
  "searchQuery": "musical",
  "genre": "broadway",
  "dateRangeFrom": "2024-01-01",
  "dateRangeTo": "2024-12-31"
}
```

**Everything the Gershwin Theatre has staged:**

```json
{
  "mode": "browseByVenue",
  "venueName": "Gershwin Theatre",
  "maxItems": 100
}
```

**Full detail with cast for a specific show:**

```json
{
  "mode": "byUrl",
  "urls": ["https://playbill.com/production/wicked-broadway-gershwin-theatre-2003"],
  "includeCast": true
}
```

**Actor credits:**

```json
{
  "mode": "byUrl",
  "urls": ["https://playbill.com/person/stephen-schwartz-vault-0000007368"]
}
```

### Use cases

- **Theatre research** — track shows by venue, genre, or opening window
- **Content databases** — build show/venue/cast datasets for ticketing or editorial products
- **Talent intelligence** — actor, writer and producer credit histories
- **Venue history** — full production archives for a specific theatre
- **Marketing & analytics** — popularity views and show categories for trend analysis

### FAQ

**Do I need an account or API key?** No. Search runs against Playbill's public Algolia search index with the same public (search-only) credentials the website itself uses; detail pages are plain public HTML.

**Is this affiliated with Playbill?** No — this is a third-party actor using Playbill's public search index and public pages. It is not affiliated with or endorsed by Playbill.

**What's the difference between `search` and `byUrl`?** `search` returns the database summary (venue, dates, synopsis, credits, categories) fast. `byUrl` fetches the full production page — including the cast list and creative team, plus person and venue pages.

**How do I get cast lists in search mode?** Set `includeCast: true`. Each show then loads its production page so `cast[]` and `credits{}` are attached (one extra request per show).

**What does `dateRangeFrom/To` mean for shows?** The show window — a record passes if its opening–closing span overlaps the requested dates. Shows still running (no closing date) pass any range from their opening onward.

**What is `genre`?** The show market: Broadway, Off-Broadway, Tour (national tours) or London. It only applies when searching the shows section.

**What does `sortBy` do?** `closingDate` orders results by the most recently closed show first, using Playbill's date-sorted replica index (`playbillcraft-beta-date`). `relevance` is the site's default ranking. It applies to the `search` and `browseByVenue` modes.

**Why are some fields missing on some records?** Older or shorter-lived shows lack e.g. closing dates or synopses; empty fields are omitted rather than filled with placeholders.

**How fresh is the data?** Live — search hits come from Playbill's production search index (updated continuously), and `byUrl` pages are fetched at run time.

### Data Source

All data comes from public surfaces of **playbill.com**: the public Algolia index `playbillcraft-beta` (application `QCDH3SSWM9`) behind the site's own search box, the server-rendered `/production/*`, `/person/*` and `/venue/*` pages, and the public `/personlistpage/person-list` cast endpoint. The site is served through a WAF that can return 403 to plain HTTP clients; the actor automatically escalates to TLS-impersonated `curl_cffi` (chrome131) requests — and optionally the Apify proxy — before failing a page.

### Limitations

- The **cast list on search results** is partial unless `includeCast` is enabled, and even then it reflects the carousel on the production page (top members per tab). Use `mode=byUrl` with `includeCast` for the full original cast (via Playbill's person-list page).
- `genre` applies only to the shows section; people and venue searches ignore it.
- Date-window filtering works on opening/preview/closing dates; shows without any dates pass through. An inverted range (`dateRangeFrom` > `dateRangeTo`) can never match and returns 0 records with a status message.
- Playbill's legacy search page (`/searchpage/search`) is WAF-blocked from datacenter IPs even with impersonation; this actor uses the site's public Algolia index instead, which is not blocked.
- The `/ajax/loadProdPeople.jsp` endpoint is Cloudflare-challenged; full cast lists are loaded from the public `/personlistpage/person-list` page instead.
- The theatre **seating-chart image** (`assets.playbill.com/venues/...`) returns 403 to all anonymous clients (no Referer unlocks it), so it cannot be served to customers or rehosted; the field is intentionally not emitted.

# Actor input Schema

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

What to fetch.

## `searchQuery` (type: `string`):

Free-text query, e.g. `wicked`, `hamilton`, `Lin-Manuel Miranda` (mode=search).

## `searchSection` (type: `string`):

Which Playbill database section to search (mode=search).

## `sortBy` (type: `string`):

Result ordering (modes=search, browseByVenue). `closingDate` sorts by most recently closed show first (uses Playbill's date-sorted index).

## `venueName` (type: `string`):

Theatre name to browse shows for, e.g. `Gershwin Theatre`, `Lyceum Theatre` (mode=browseByVenue).

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

Production, person or venue page URLs, e.g. `https://playbill.com/production/wicked-broadway-gershwin-theatre-2003`.

## `genre` (type: `string`):

Constrain shows to a market/genre (modes=search, browseByVenue; shows section only).

## `containsKeyword` (type: `string`):

Client-side filter — title/synopsis must contain this substring (case-insensitive).

## `dateRangeFrom` (type: `string`):

Only emit shows running on or after this date (based on opening/closing dates).

## `dateRangeTo` (type: `string`):

Only emit shows running on or before this date (based on opening/closing dates).

## `includeCast` (type: `boolean`):

Enrich show records with cast list and creative credits by loading each production page (adds one request per show; modes=search, browseByVenue, byUrl).

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

Hard cap on emitted records.

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

Optional Apify proxy. Only engaged automatically if playbill.com returns 403/429 on the default connection.

## Actor input object example

```json
{
  "mode": "search",
  "searchQuery": "wicked",
  "searchSection": "shows",
  "sortBy": "relevance",
  "venueName": "Gershwin Theatre",
  "urls": [],
  "genre": "broadway",
  "includeCast": false,
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `shows` (type: `string`):

Dataset containing all scraped Playbill records.

# 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",
    "searchQuery": "wicked",
    "searchSection": "shows",
    "sortBy": "relevance",
    "venueName": "Gershwin Theatre",
    "urls": [],
    "genre": "broadway",
    "includeCast": false,
    "maxItems": 50,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/playbill-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",
    "searchQuery": "wicked",
    "searchSection": "shows",
    "sortBy": "relevance",
    "venueName": "Gershwin Theatre",
    "urls": [],
    "genre": "broadway",
    "includeCast": False,
    "maxItems": 50,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/playbill-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",
  "searchQuery": "wicked",
  "searchSection": "shows",
  "sortBy": "relevance",
  "venueName": "Gershwin Theatre",
  "urls": [],
  "genre": "broadway",
  "includeCast": false,
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call crawlerbros/playbill-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,crawlerbros/playbill-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/NHbe87c4y4vZeKbcO/builds/C8o3GMnxzteAmZT4q/openapi.json
