# YouTube Transcript Scraper (`chilly_damask/youtube-transcript-scraper`) Actor

Extract YouTube video transcripts (manual + auto-generated captions) with timestamps and full plain text from video URLs or IDs. No login, no API key, no browser. Pay only per transcript returned. CSV/JSON.

- **URL**: https://apify.com/chilly\_damask/youtube-transcript-scraper.md
- **Developed by:** [Jaxx](https://apify.com/chilly_damask) (community)
- **Categories:** Videos, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 1,000 transcript returneds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## YouTube Transcript Scraper (Pay Per Transcript)

**Turn a list of YouTube video URLs into clean, timestamped transcripts — manual and auto-generated captions, in every language the video publishes. You pay only when a transcript is actually returned. No transcript, no charge.**

Feed the actor video URLs (any form: `watch?v=`, `youtu.be`, Shorts, embeds, live links) or bare video ids. It resolves each video through the **same public player endpoint every signed-out YouTube client calls**, reads the caption track list, fetches the transcript for each selected language, and returns timestamped segments plus the full plain text — signed out, no login, no API keys, no browser.

- 📝 **Timestamped segments** — `{ start, dur, text }` per caption cue (seconds), plus the whole transcript as one plain-text string
- 🌍 **Every published language** — or only the codes you ask for (`en`, `de`, `pt-BR`, …)
- 🤖 **Manual + auto-generated** — auto-generated (speech-recognition) tracks are flagged `isAutoGenerated: true` and can be excluded
- 📊 Video metadata on every record: title, channel, video length, and the full list of available caption languages
- 💰 **Pay-per-result** — priced per transcript returned, not per subscription. A video with **no captions costs you nothing**.

---

### 🎯 Best for

Self-identify in two seconds — this actor is built for:

- **LLM / RAG pipelines** — turn channels' videos into clean text for embedding, summarization, or fine-tuning corpora.
- **Content repurposing** — pull the transcript of your own or a source video to draft articles, newsletters, or show notes.
- **Research & media monitoring** — search what was actually *said* across a list of videos, with timestamps to jump to.
- **Subtitle & localization workflows** — grab the existing caption tracks (and see which languages exist) before translating.
- **SEO & competitive analysis** — analyze the full spoken content of ranking videos, not just titles and descriptions.

---

### 🔒 What makes this scraper different (and safer)

It runs **signed out** and reads only **public** surfaces — the public YouTube player endpoint (the JSON API the YouTube site itself calls before you ever log in) and the **signed public timedtext URLs** it returns. There is no login, no cookie, no CAPTCHA, no user API key, and no browser.

#### Where the transcripts come from

Public surfaces, signed out:

1. the video's **caption track list** from the public player endpoint — every manual and auto-generated track the video publishes, and
2. each track's **timedtext URL** — the same URL the YouTube player fetches to render captions on screen.

#### What it deliberately does NOT do

- ❌ **Does not log into anything** and does not touch private, unlisted-restricted, or members-only data. A video whose captions aren't publicly served simply comes back as an honest error row.
- ❌ **Does not fabricate transcripts.** There is no speech-to-text model in this actor — it returns exactly the caption tracks YouTube publishes, flagged manual vs auto-generated. If a video has no captions at all, you get `no_captions_available`, not a guess.

---

### 🎬 Scope & limits (read this)

- **Captions only.** A video with captions disabled (music videos and animations are common cases) has no public transcript surface — it returns a free `status: "error"` row with `errorDetail: "no_captions_available"`. That's an honest scope limit, not a bug.
- **Auto-generated quality is YouTube's.** `isAutoGenerated: true` tracks are YouTube's own speech recognition — mis-hearings, missing punctuation, and `[Music]` markers included. Manual tracks are whatever the uploader published.
- **No auto-translation.** The actor returns the tracks the video actually publishes. Requesting a language the video doesn't have yields `no_matching_caption_track` (with the available languages listed on the record) rather than a machine translation.
- **Age-restricted / region-locked / private videos** may be unplayable signed out; they come back as `video_unavailable (…)` error rows — free, never charged.

---

### ⚙️ How it works

Plain HTTP — no browser, no key, no login:

1. **Extract the video id** from each input URL or bare id (`watch?v=`, `youtu.be/`, `/shorts/`, `/embed/`, `/live/` all supported), deduped run-wide.
2. **Resolve the video** via the public player endpoint (`youtube.com/youtubei/v1/player`) → title, channel, length, playability, and the caption track list.
3. **Select tracks**: your `languages` filter (empty = all available), the `includeAutoGenerated` switch, and `preferManual` (when a language has both a manual and an auto track, return only the manual one so you aren't billed twice for near-identical content).
4. **Fetch each track's signed timedtext URL** and parse the response — all three of YouTube's transcript wire formats (srv3 XML, classic XML, json3) are handled by a dependency-free parser.
5. **Emit one record per transcript** with segments, plain text, word/segment counts, and the full list of available caption languages.

Built-in resilience (shared with the maintainer's other scrapers):

- up to **3 retries** per request with backoff, and a body-download-safe timeout,
- a **response-size cap** so a runaway response can't exhaust memory,
- **run-global de-duplication** by video id, so the same video submitted twice (or as URL + id) is fetched, charged, and emitted once,
- **honest error output** — an unavailable video, a caption-less video, or a failed track fetch is written to the dataset as `{ "status": "error", "errorDetail": "…" }` rather than silently dropped or crashing the run.

---

### ▶️ How to use (no code required)

1. Create a free Apify account.
2. Open this actor and paste video links into **Video URLs** (or bare ids into **Video IDs**).
3. (Optional) restrict **Languages** (e.g. `en`), toggle **Include auto-generated captions**, and choose whether you want segments, plain text, or both.
4. Click **Start**.
5. Watch rows appear in the **Output** tab, then export the dataset as JSON, CSV, Excel, XML, or HTML — or pull it via the API.

---

### 📥 Input

| Field | Type | Default | Notes |
|---|---|---|---|
| `videoUrls` | array of strings | `[]` | Video URLs in any common form — `watch?v=…`, `youtu.be/…`, `/shorts/…`, `/embed/…`, `/live/…` — or bare 11-char ids. |
| `videoIds` | array of strings | `[]` | Bare 11-character video ids. Merged with `videoUrls` and deduped. |
| `languages` | array of strings | `[]` | Caption language codes to return. A base code matches regional variants (`en` matches `en-US`). **Empty = every language the video publishes.** |
| `includeAutoGenerated` | boolean | `true` | Include YouTube's auto-generated (speech-recognition) tracks. |
| `preferManual` | boolean | `true` | When a language has both manual and auto-generated tracks, return only the manual one. |
| `includeSegments` | boolean | `true` | Emit the timestamped `segments` array. |
| `includeFullText` | boolean | `true` | Emit the joined plain-text `transcript` string. |

#### Example input

```json
{
  "videoUrls": [
    "https://www.youtube.com/watch?v=jNQXAC9IVRw",
    "https://youtu.be/dQw4w9WgXcQ"
  ],
  "languages": ["en"],
  "includeAutoGenerated": true,
  "preferManual": true,
  "includeSegments": true,
  "includeFullText": true
}
````

***

### 📤 Output

One record per **transcript** (one video × one caption track), written to the dataset as results come in. A video with three published languages and no language filter yields three records. Export as JSON, CSV, Excel, XML, or HTML, or read it through the API.

```json
{
  "videoId": "jNQXAC9IVRw",
  "videoUrl": "https://www.youtube.com/watch?v=jNQXAC9IVRw",
  "title": "Me at the zoo",
  "channelName": "jawed",
  "lengthSeconds": 19,
  "language": "en",
  "languageName": "English",
  "isAutoGenerated": false,
  "segments": [
    { "start": 1.2, "dur": 2.16, "text": "All right, so here we are, in front of the elephants" }
  ],
  "transcript": "All right, so here we are, in front of the elephants the cool thing about these guys is that they have really... really really long trunks and that's cool (baaaaaaaaaaahhh!!) and that's pretty much all there is to say",
  "segmentCount": 6,
  "wordCount": 39,
  "charCount": 217,
  "availableLanguages": [
    { "language": "en", "languageName": "English", "isAutoGenerated": false },
    { "language": "de", "languageName": "German", "isAutoGenerated": false }
  ],
  "requestedLanguages": ["en"],
  "sourceInput": "https://www.youtube.com/watch?v=jNQXAC9IVRw",
  "scrapedAt": "2026-07-15T00:00:00.000Z",
  "status": "ok",
  "errorDetail": null
}
```

Field notes:

- **`segments`** — one `{ start, dur, text }` object per caption cue; times in **seconds**. Omitted when `includeSegments` is off.
- **`transcript`** — the whole transcript joined into one whitespace-normalized string. Omitted when `includeFullText` is off.
- **`isAutoGenerated`** — `true` for YouTube's speech-recognition tracks, `false` for uploader-published captions.
- **`availableLanguages`** — every caption track the video publishes, whether or not it was requested — so a `no_matching_caption_track` error row still tells you what *is* available.
- **`status`** — `"ok"` for a returned transcript, `"error"` otherwise, with a human-readable `errorDetail`: `invalid_video_url_or_id`, `video_unavailable (…)`, `no_captions_available`, `no_matching_caption_track`, `transcript_fetch_failed (…)`, or `transcript_empty (…)`. Error rows are kept, not dropped — and never charged.

***

### 💰 Pricing (pay-per-event)

You are charged a **fixed price per result event** — not for platform usage or compute time.

| Event | Price | Per 1,000 | When you're charged |
|---|---|---|---|
| `transcript-returned` | **$0.0025** | **$2.50 / 1,000** | Once per **transcript actually returned** (one video × one caption track, `status: "ok"`). A video with **no captions is free**. |

**No-result-free is the core trust mechanic:** you never pay for a video that yields nothing — no captions, unavailable, bad URL, or a failed fetch all come back as free `status: "error"` rows, never as a phantom charge for data that does not exist.

**What a run costs — a worked example:** you submit **300 video URLs** with `languages: ["en"]`; **250** have an English track and return one transcript each → **250 × $0.0025 = $0.625**. The **50** videos with no captions (or unavailable) cost **nothing**. Total: **$0.625**.

> The price above is exactly what you're billed — nothing for platform usage or compute on top. Comparable Store actors price differently; compare the live listings and pick what fits your volume.

***

### ❓ FAQ

**Do I pay for videos that have no captions?**
No. You are charged only when a transcript is actually returned (`status: "ok"`). A caption-less video, an unavailable video, an invalid URL, or a failed fetch costs you nothing.

**One video came back as several records — why?**
The record grain is one **transcript**, i.e. one video × one caption track. With `languages` empty (the default) you get every language the video publishes. Set `languages: ["en"]` if you only want one.

**Does it translate captions into languages the video doesn't have?**
No. It returns only tracks the video actually publishes — auto-translation is deliberately out of scope (see Roadmap). The `availableLanguages` field on every record shows what exists.

**Are auto-generated transcripts accurate?**
They are YouTube's own speech recognition, returned verbatim and flagged `isAutoGenerated: true` — expect mis-hearings and missing punctuation, especially with music or accents. Prefer manual tracks when they exist (`preferManual` does that automatically).

**Can I test with a small list first?**
Yes. Start with two or three URLs, confirm the output looks right, then scale up. Each transcript is billed individually, so a small test costs cents.

**Can I run it on a schedule or from my own code?**
Yes. Apify lets you run this actor from the Console UI, schedule it, call it via the Apify API, drive it with the `apify-client` SDKs for JavaScript and Python, run it from the Apify CLI, or connect it through an MCP server — and wire the output into Make, Zapier, Slack, Google Sheets, or a webhook.

**Is it legal to scrape this?**
The actor reads only publicly available data, signed out — the same caption files YouTube serves to any visitor. You are responsible for how you use the content: transcripts may be copyrighted by the video's creator, so make sure your use (quotation, research, fair use, licensed reuse) is legitimate, and comply with applicable law and YouTube's terms. If unsure, consult your own legal counsel.

**What happens when a fetch fails mid-run?**
The request is retried up to 3 times with backoff, then written to the dataset as a `{ "status": "error", "errorDetail": "…" }` row. One bad video never crashes the run — you get an honest record of what failed and are not charged for it.

***

### 🔌 API-ready

This actor is a drop-in piece of a pipeline. Apify auto-generates integration snippets for it — JavaScript (`apify-client`), Python (`apify-client`), the Apify CLI, the REST API, an OpenAPI spec, and an MCP server — so you can call it from your own stack or an agent workflow. See the **API** tab on the actor page.

***

### Maintainer

Published by **Jaxx**. Categories: **Videos** · **AI & LLM tools**.

Found a video that should have parsed but didn't, or a field you'd like added? Open an issue on the actor's **Issues** tab — bug reports and extraction edge cases are actively reviewed.

# Actor input Schema

## `videoUrls` (type: `array`):

YouTube video URLs in any common form — watch?v=…, youtu.be/…, /shorts/…, /embed/…, /live/… — or bare 11-character video ids. Duplicates (including the same video given as URL and id) are deduped run-wide.

## `videoIds` (type: `array`):

Bare 11-character YouTube video ids (the part after watch?v=). Convenience alternative to full URLs — both inputs are merged and deduped.

## `languages` (type: `array`):

Caption language codes to return (e.g. "en", "de", "pt-BR"). A base code matches its regional variants ("en" matches "en-US"). Leave EMPTY to return every language the video has published.

## `includeAutoGenerated` (type: `boolean`):

Include YouTube's auto-generated (speech-recognition) caption tracks. Turn off to return only human-uploaded captions.

## `preferManual` (type: `boolean`):

When a video has BOTH a manual and an auto-generated track in the same language, return only the manual one — so you are not charged twice for near-identical content. Turn off to receive both.

## `includeSegments` (type: `boolean`):

Emit the segments array — one { start, dur, text } object per caption cue, times in seconds. Turn off for a leaner record with plain text only.

## `includeFullText` (type: `boolean`):

Emit the transcript field — the whole transcript joined into one plain-text string. Turn off if you only need the timestamped segments.

## Actor input object example

```json
{
  "videoUrls": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "https://youtu.be/UF8uR6Z6KLc"
  ],
  "videoIds": [
    "dQw4w9WgXcQ"
  ],
  "languages": [
    "en",
    "de"
  ],
  "includeAutoGenerated": true,
  "preferManual": true,
  "includeSegments": true,
  "includeFullText": true
}
```

# 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 = {
    "videoUrls": [
        "https://www.youtube.com/watch?v=jNQXAC9IVRw"
    ],
    "videoIds": [],
    "languages": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("chilly_damask/youtube-transcript-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 = {
    "videoUrls": ["https://www.youtube.com/watch?v=jNQXAC9IVRw"],
    "videoIds": [],
    "languages": [],
}

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

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

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

```

## CLI example

```bash
echo '{
  "videoUrls": [
    "https://www.youtube.com/watch?v=jNQXAC9IVRw"
  ],
  "videoIds": [],
  "languages": []
}' |
apify call chilly_damask/youtube-transcript-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=chilly_damask/youtube-transcript-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "YouTube Transcript Scraper",
        "description": "Extract YouTube video transcripts (manual + auto-generated captions) with timestamps and full plain text from video URLs or IDs. No login, no API key, no browser. Pay only per transcript returned. CSV/JSON.",
        "version": "1.0",
        "x-build-id": "9pRN1pvmlv1Bv6Nsz"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/chilly_damask~youtube-transcript-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-chilly_damask-youtube-transcript-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/chilly_damask~youtube-transcript-scraper/runs": {
            "post": {
                "operationId": "runs-sync-chilly_damask-youtube-transcript-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/chilly_damask~youtube-transcript-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-chilly_damask-youtube-transcript-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "videoUrls": {
                        "title": "Video URLs",
                        "type": "array",
                        "description": "YouTube video URLs in any common form — watch?v=…, youtu.be/…, /shorts/…, /embed/…, /live/… — or bare 11-character video ids. Duplicates (including the same video given as URL and id) are deduped run-wide.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "videoIds": {
                        "title": "Video IDs",
                        "type": "array",
                        "description": "Bare 11-character YouTube video ids (the part after watch?v=). Convenience alternative to full URLs — both inputs are merged and deduped.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "languages": {
                        "title": "Languages",
                        "type": "array",
                        "description": "Caption language codes to return (e.g. \"en\", \"de\", \"pt-BR\"). A base code matches its regional variants (\"en\" matches \"en-US\"). Leave EMPTY to return every language the video has published.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "includeAutoGenerated": {
                        "title": "Include auto-generated captions",
                        "type": "boolean",
                        "description": "Include YouTube's auto-generated (speech-recognition) caption tracks. Turn off to return only human-uploaded captions.",
                        "default": true
                    },
                    "preferManual": {
                        "title": "Prefer manual over auto-generated",
                        "type": "boolean",
                        "description": "When a video has BOTH a manual and an auto-generated track in the same language, return only the manual one — so you are not charged twice for near-identical content. Turn off to receive both.",
                        "default": true
                    },
                    "includeSegments": {
                        "title": "Include timestamped segments",
                        "type": "boolean",
                        "description": "Emit the segments array — one { start, dur, text } object per caption cue, times in seconds. Turn off for a leaner record with plain text only.",
                        "default": true
                    },
                    "includeFullText": {
                        "title": "Include full plain text",
                        "type": "boolean",
                        "description": "Emit the transcript field — the whole transcript joined into one plain-text string. Turn off if you only need the timestamped segments.",
                        "default": true
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
