# TVmaze Series Metadata Export (`automation-lab/tvmaze-series`) Actor

Export TVmaze series metadata from supplied show IDs: names, genres, premiere dates, networks and canonical URLs for recurring catalog enrichment.

- **URL**: https://apify.com/automation-lab/tvmaze-series.md
- **Developed by:** [Automation Lab](https://apify.com/automation-lab) (community)
- **Categories:** Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.43 / 1,000 item extracteds

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

## TVmaze Series Metadata Export

Export **TVmaze series** metadata from known show IDs for recurring entertainment catalog enrichment. Get one flat row per existing series with its title, genres, premiere date, broadcaster, streaming channel and canonical TVmaze URL.

### Who is it for?

This Actor is for catalog editors, entertainment directory operators and analysts who already maintain TVmaze identifiers. It retrieves current metadata, not episodes, cast, schedules or historical snapshots.

### Why use this Actor?

Use a repeatable Apify job instead of maintaining individual API requests and output formatting. The exporter deduplicates supplied IDs, validates source records, handles temporary API failures and saves flat rows suitable for CSV and database joins. No source account, API key, browser or proxy is needed.

The underlying TVmaze API is publicly available. This Actor provides managed execution, typed exports and integrations; it does not provide exclusive source access or additional licensed data.

### Getting started

1. Find the numeric TVmaze IDs in your catalog or in TVmaze show URLs.
2. Enter the IDs as a JSON array in **TVmaze series IDs**.
3. Choose a maximum number of successful series records.
4. Run the Actor and open the default dataset.
5. Export JSON, CSV, Excel or other formats supported by Apify.

Example input:

```json
{"seriesIds": [1, 2, 3], "maxItems": 100}
```

### Input parameters

| Parameter | Meaning |
|---|---|
| `seriesIds` | Required array of 1–10000 positive integer TVmaze show IDs. IMDb/TVDB identifiers and URL strings are not accepted. |
| `maxItems` | Global successful-record limit, 1–10000, default 100. Zero/unlimited is not supported. |

IDs are processed in supplied order after deduplication. A duplicate ID is fetched once. Missing IDs are skipped and do not consume the record limit. Processing stops at the limit, so later IDs may not be visited. Unknown input fields are rejected rather than silently ignored.

### Extracted TVmaze series data

| Field | Meaning |
|---|---|
| `showId` | Numeric TVmaze show ID, useful as a stable catalog join key. |
| `name` | Source series title. |
| `genres` | Array of TVmaze genre labels. |
| `premiered`, `ended` | Source date strings or null when not available. |
| `network` | Linear broadcaster name or null. |
| `webChannel` | Streaming service/channel name or null. |
| `countryCode` | Network country code, otherwise web-channel country code, or null. |
| `url` | Canonical TVmaze show page URL. |
| `language` | Source language or null. |
| `status`, `type` | Source status and series type, or null. |
| `scrapedAt` | ISO retrieval timestamp, not the source's last update time. |

Network and web-channel values are independent. A streaming-only series may have no network. Missing source fields remain null; the Actor does not infer them.

### Output example

A representative show lookup returns:

```json
{
  "showId": 1,
  "name": "Under the Dome",
  "genres": ["Drama", "Science-Fiction", "Thriller"],
  "premiered": "2013-06-24",
  "ended": "2015-09-10",
  "network": "CBS",
  "webChannel": null,
  "countryCode": "US",
  "url": "https://www.tvmaze.com/shows/1/under-the-dome",
  "language": "English",
  "status": "Ended",
  "type": "Scripted",
  "scrapedAt": "2026-10-02T14:00:00.000Z"
}
```

The timestamp illustrates the output format and changes on every retrieval. Actual source metadata can change.

### How much does it cost to export TVmaze series metadata?

Pricing is pay-per-event: a one-time start event plus one item event for each successfully exported unique series. Missing IDs and retries have no item charge. A valid run containing only missing IDs still incurs the start fee. Invalid input is rejected before the start charge.

The start fee is $0.0005 per run. Per-series prices depend on your Apify spend tier:

| Tier | Per series |
|---|---:|
| FREE | $0.000828 |
| BRONZE | $0.00072 |
| SILVER | $0.0005616 |
| GOLD | $0.000432 |
| PLATINUM | $0.000432 |
| DIAMOND | $0.000432 |

Spend-tier eligibility depends on qualifying aggregate monthly Apify Store spend, not this Actor's individual batch size.

Estimated BRONZE examples: 1 record $0.00122, 10 records $0.0077, 100 records $0.0725. Billing limits can stop a run before all requested records are delivered. These are usage estimates, not guaranteed invoices.

### Limits and failure behavior

The exporter makes serial HTTPS requests to TVmaze's public show endpoint and pauses between successful results. Temporary network failures, HTTP 429 and 5xx responses receive at most three attempts per ID with bounded backoff. Each request has a 20-second timeout. Permanent HTTP errors and malformed source responses fail the run.

HTTP 404 is an expected missing show, not a successful record. If an upstream failure occurs after earlier rows were saved, the run fails and those rows remain available. Do not treat a failed partial dataset as a complete refresh. A retry run is a new billable run; deduplication applies within a run, not across your scheduled runs.

The default platform timeout is five minutes. Large lists may require a longer run timeout or smaller batches. This is an ID-based exporter, not a complete-catalog enumeration tool.

### Integrations

- Schedule runs with the same IDs to refresh a catalog; compare datasets externally using `showId`.
- Join CSV exports with your content-management system or a warehouse lookup table.
- Use Apify webhooks, Make, Zapier or n8n to route completed datasets to your database.
- Keep `scrapedAt` as the refresh timestamp; it is not a change-detection signal.

The Actor does not send change alerts or maintain historical state. Your integration owns scheduling, comparison and upserts.

### API usage

Use an Apify token through an environment variable. Avoid placing tokens in shared URLs or logs.

#### cURL

```bash
curl -X POST -H "Authorization: Bearer $APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  'https://api.apify.com/v2/acts/automation-lab~tvmaze-series/run-sync-get-dataset-items' \
  -d '{"seriesIds":[1,2,3],"maxItems":100}'
```

#### JavaScript

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/tvmaze-series').call({
  seriesIds: [1, 2, 3], maxItems: 100,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Python

```python
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/tvmaze-series').call(
    run_input={'seriesIds': [1, 2, 3], 'maxItems': 100})
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)
```

### MCP usage

Once available to your account, connect the Actor-scoped Apify MCP endpoint. Actor execution is billable; inspect the tool schema and authorize runs deliberately.

#### Claude Code

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/tvmaze-series"
```

#### Claude Desktop, Cursor, and VS Code

Use the HTTP server entry supported by your client's MCP configuration and authenticate through its supported Apify flow:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/tvmaze-series"
    }
  }
}
```

Example prompts:

- “Export TVmaze show IDs 1, 2 and 3 and show their networks and premiere dates.”
- “Fetch these 20 TVmaze IDs, then prepare a table keyed by showId for my catalog.”

Client configuration formats can differ. Private/unpublished Actors may not be exposed by hosted discovery.

#### Hosted MCP: start once and retrieve bounded results

1. **Discover only the needed tools.** Keep the Actor-scoped URL above and inspect `tools/list` for actual tool names and argument schemas (follow a discovery cursor if supplied). Actor selection also adds `get-actor-run`, `get-dataset-items`, `get-key-value-store-record` and `abort-actor-run`; it does not expose exactly one tool. Use only the Actor/run/dataset subset needed here. Read-only discovery does not authorize execution or aborting a run.
2. **Authorize one billable start.** Invoke the discovered Actor tool once with `{"seriesIds":[1,2,3],"maxItems":100}`. Retain its run ID, status and storage IDs, including `defaultDatasetId`; these are metadata, not result rows. The `call-actor` wait is bounded by `waitSecs` (0–45 seconds, default 30). For example, choose 30 seconds and a client request timeout of 40 seconds, within a total 120-second consumer deadline.
3. **Follow that SAME run.** If nonterminal, use `get-actor-run` with the saved run ID, backing off 2, 4, 8 seconds then at most 10 seconds, with requests capped by the remaining deadline. On a client timeout, recover/check the known run rather than start again. If no run ID was received, report uncertain start status instead of blindly rerunning. At the 120-second deadline, report pending with the run ID and stop polling; this does not stop the Actor. Report FAILED, TIMED-OUT or ABORTED honestly; available rows are partial, not a successful full refresh. Only abort with explicit authorization.
4. **Retrieve actual rows with projection and paging.** After SUCCEEDED, use `get-dataset-items` with the returned dataset ID and explicit `limit=20`, `offset=0`, and `fields="showId,name,genres,premiered,network,webChannel,url"`, using the discovered argument schema. Request untransformed JSON and advance source offsets by the consumed source page, using pagination metadata to detect exhaustion. Do not infer source offsets from transformed row counts; filtering or unwinding can change those counts.
5. **Bound total model-context content.** Across all pages, admit at most 100 rows or 64 KiB (65,536 bytes) of serialized UTF-8 result content, whichever comes first. Enforce this in the client/host before injecting pages into model context, counting every admitted page or summary. For an oversized row/page, omit or summarize within the remaining byte budget and disclose the omission; do not silently claim completeness. If your client cannot intercept oversized responses, it cannot guarantee this hard byte ceiling: use a small bounded preview and keep large/full results outside model context, rather than request unbounded results.
6. **Disclose preview versus full export.** Stop at exhaustion or the total budget. Report admitted row count, byte count, next source offset and any omitted rows, plus partial/truncated status whenever incomplete. For the three-ID example, expect up to three existing series, not 100 rows. Obtain full JSON/CSV exports from the run's default dataset in Apify Console or through downstream dataset downloads outside model context. This consumer preview budget does not change Actor `maxItems`, extraction scope or stored output fields.

Example follow-up prompt: “Follow the same run without restarting it, within a 120-second deadline. Once successful, preview the selected catalog fields in 20-row source pages, at most 100 rows and 64 KiB total UTF-8 context. State whether the preview is complete and give the dataset export path and continuation offset.”

Tool discovery transport size is not model-visible context. Client-side discovery caching, progressive loading and prompt caching vary by client and capabilities; no token or context-savings claim is made here.

### Legality and responsible use

TVmaze is an independent service. This Actor is not affiliated with or endorsed by TVmaze. Follow the [TVmaze API documentation](https://www.tvmaze.com/api) and its attribution/share-alike requirements, including [CC BY-SA](https://creativecommons.org/licenses/by-sa/4.0/), when reusing source data. Preserve TVmaze attribution and canonical links in downstream products. You are responsible for checking suitability for your use.

The Actor uses Apify's standard user terms and adds no custom agreement. No AI models are used in runtime extraction or output generation.

### Data handling

Only show metadata and supplied numeric IDs are processed. No account cookies or personal profiles are requested. TVmaze receives show-ID lookups. Apify hosts input, datasets and logs according to your account's retention settings; delete them through Apify when no longer needed. There is no persistent cross-run cache.

Failed operations send sanitized diagnostic input, exceptions and actor/build/run IDs to our private GlitchTip service for repair. Secret fields and URL queries are removed and reports are retained for 30 days. Do not submit credentials in input. Apify storage retention is separate from diagnostic retention.

### Troubleshooting and FAQ

**Why is my output empty?** All supplied IDs may be missing. Check the run log for 404 warnings and confirm that you supplied TVmaze show IDs, not IMDb IDs.

**Why are there fewer rows than IDs?** Duplicates, missing IDs, the successful-record limit, a billing cap or a failed/timed-out run may explain the difference. Check run status before treating output as complete.

**Can I search by title or fetch episodes?** No. This Actor accepts only show IDs and exports series metadata. It does not fetch episodes, cast or schedules.

**Why is the network null?** Streaming-only or incomplete records may have no linear broadcaster. Check `webChannel`; null is not replaced with a guessed value.

**How do I get help?** Open an issue on the Actor's Apify page with the run URL and a minimal non-sensitive input example.

### Refreshing an existing catalog

Store each successful dataset as a dated snapshot or upsert its rows by `showId`. Keep old values when the refresh fails, and distinguish a missing ID warning from an upstream failure. To avoid unintentionally truncating a catalog, set `maxItems` to the number of unique IDs in that batch. Validate run status and expected row counts in your integration before replacing production catalog data.

### Related automation

This is a standalone TVmaze series catalog workflow. No unrelated Actor is required. Use Apify's dataset export and your own catalog integration for the next step rather than assuming another Actor supplies unsupported schedule or episode coverage.

# Changelog

This Actor's version history is a separate document: https://apify.com/automation-lab/tvmaze-series/changelog.md

# Actor input Schema

## `seriesIds` (type: `array`):

Supply 1–10000 positive integer TVmaze show IDs, not IMDb or TVDB IDs. Duplicate IDs are fetched once, preserving first occurrence order. Missing IDs (HTTP 404) are skipped without an item charge.

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

Global maximum of successful unique show records per run, from 1–10000; default 100. Zero/unlimited is unsupported. Missing IDs do not consume the limit. Processing stops once this many records are saved; remaining supplied IDs are not fetched.

## Actor input object example

```json
{
  "seriesIds": [
    1,
    2,
    3
  ],
  "maxItems": 10
}
```

# Actor output Schema

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

Default dataset of exported TVmaze series 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 = {
    "seriesIds": [
        1,
        2,
        3
    ],
    "maxItems": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/tvmaze-series").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 = {
    "seriesIds": [
        1,
        2,
        3,
    ],
    "maxItems": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/tvmaze-series").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 '{
  "seriesIds": [
    1,
    2,
    3
  ],
  "maxItems": 10
}' |
apify call automation-lab/tvmaze-series --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/tvmaze-series"
        }
    }
}
```

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/LYZLxuwF1m6sdo5Wk/builds/X6NREOiTjHX1eTH99/openapi.json
