# Substack Scraper - posts, comments & authors (`doggo/substack-scraper-posts-comments-authors`) Actor

Scrape Substack newsletters at scale: full post archives with article text, comments, author profiles, and publication stats like subscriber counts. Works with any Substack URL or custom domain. Fast API-based scraping with no browser, pay per result. Export to CSV, JSON, Excel, or API.

- **URL**: https://apify.com/doggo/substack-scraper-posts-comments-authors.md
- **Developed by:** [Doggo](https://apify.com/doggo) (community)
- **Categories:** Social media, Lead generation, News
- **Stats:** 4 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $4.00 / 1,000 posts

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Substack Scraper

**Scrape any Substack newsletter, post, author, or comment — fast, cheap, and at scale.**

This Apify actor extracts structured data from Substack publications via their public JSON API. No browser, no JavaScript rendering, no login required. Built for newsletter research, content monitoring, author discovery, competitive intelligence, and LLM training datasets.

### What you can scrape

- **Substack posts** — title, subtitle, full HTML and plain-text body, word count, publish date, tags, cover image, paywall status, reactions, comment count, restacks
- **Substack publications** — name, subdomain, custom domain, description, logo, category, language, subscriber count (when public), founding plan
- **Substack authors** — profile, handle, bio, photo, the publications they write for, the publications they subscribe to
- **Substack comments** — full nested comment threads, author handles, publish dates, reactions, reply depth

Works with any Substack URL: `https://*.substack.com`, custom domains (`https://stratechery.com`), individual post URLs, `https://substack.com/@handle` author profiles, and `https://open.substack.com/pub/...` share links.

### Why use this Substack scraper

- **Pay only for data, not for browser time** — no Playwright, no rendering overhead, no per-minute compute billing. You pay per result, and failed requests are never charged.
- **Full archives, not just the front page** — paginates through the entire publication archive until the very first post.
- **Clean, typed output** — one dataset with a `type` field (`post` / `publication` / `author` / `comment`) and per-type table views, so you can export straight to BI tools, CSV, JSON, Excel, or Google Sheets.
- **No duplicates, no surprises** — every post is delivered exactly once, limits are enforced even across platform restarts, and proxy rotation is handled for you.

### Common use cases

- **Newsletter research** — download the full archive of a competitor's Substack for content analysis, topic clustering, or SEO research
- **Content monitoring** — schedule a daily run with `maxPostsPerPublication: 5` to capture new posts from a tracked list of newsletters and pipe to Slack or email
- **Author discovery and lead generation** — crawl author profiles to map who writes for which publications, then export handles for outreach
- **LLM training data** — bulk-extract long-form Substack content (with word counts and metadata) for fine-tuning datasets
- **Competitive intelligence** — track subscriber counts, post frequency, paywall strategy, and engagement metrics (reactions, comments, restacks) across a competitor set
- **Academic and journalism research** — gather statements, essays, and commentary from Substack writers with citable timestamps
- **Archiving and backup** — export your own Substack publication before a migration

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `startUrls` | array of URLs | — | Substack publication, post, or author URLs. Leave empty only when using Discovery mode |
| `mode` | `posts` / `publication` | `posts` | What to pull for each publication URL |
| `maxPostsPerPublication` | integer | 50 | Cap per publication. `0` = entire archive. Lower = cheaper |
| `includeContent` | boolean | true | Fetch each post's full HTML body |
| `includeComments` | boolean | false | Fetch comments for each post (each comment is a separate result) |
| `onlyFreePosts` | boolean | false | Skip paid / subscriber-only posts in archives |
| `searchQuery` | string | — | Filter the publication archive by keyword |
| `discoveryMode` | `none` / `leaderboard` / `search` | `none` | Auto-discover many publications without providing URLs |
| `discoveryQuery` | string | — | Keyword for `search` discovery |
| `maxPublicationsToDiscover` | integer | 25 | Cap on discovered publications. Lower = cheaper |
| `maxConcurrency` | integer | 5 | Parallel requests |

#### Discovery mode — scrape many publications without a list

If you don't have a list of specific newsletters, turn on **Discovery mode** and the actor will find publications for you:

- **Top publications** (`leaderboard`) — seeds from 5 curated top Substacks and expands through each publication's recommendations until the limit is hit
- **Search** (`search`) — same expansion, plus your `discoveryQuery` keyword filters every discovered publication's archive

Each discovered publication is then scraped using the same `mode` / `maxPostsPerPublication` settings as `startUrls`, so you can go from zero URLs to a full corpus in one run. Discovery is **off by default** — a discovery run scrapes many publications and produces a correspondingly large dataset.

```json
{
    "discoveryMode": "search",
    "discoveryQuery": "AI",
    "maxPublicationsToDiscover": 50,
    "mode": "posts",
    "maxPostsPerPublication": 20,
    "includeContent": true
}
````

### Example input

```json
{
    "startUrls": [
        { "url": "https://www.thefitzwilliam.com" },
        { "url": "https://noahpinion.substack.com" },
        { "url": "https://substack.com/@mattyglesias" }
    ],
    "mode": "posts",
    "maxPostsPerPublication": 100,
    "includeContent": true,
    "includeComments": false
}
```

### Output

All records land in the run's dataset with a `type` discriminator (`post`, `publication`, `author`, `comment`). The Output tab offers per-type table views (**Posts**, **Publications**, **Authors**, **Comments**); for exports, filter on the `type` field to split record types into separate files.

#### Post record

```json
{
    "type": "post",
    "id": 123456,
    "title": "Why newsletters won",
    "slug": "why-newsletters-won",
    "url": "https://example.substack.com/p/why-newsletters-won",
    "publication": "example",
    "publicationName": "The Example",
    "publishedAt": "2026-02-01T14:00:00Z",
    "audience": "everyone",
    "isPaid": false,
    "author": "Jane Author",
    "authors": [{ "id": 99, "name": "Jane Author", "handle": "janeauthor" }],
    "bodyHtml": "<p>...</p>",
    "bodyText": "...",
    "wordcount": 1842,
    "reactionCount": 213,
    "commentCount": 42,
    "restacks": 18,
    "postTags": ["media", "business"]
}
```

#### Publication record

```json
{
    "type": "publication",
    "id": 42,
    "name": "The Example",
    "subdomain": "example",
    "customDomain": null,
    "url": "https://example.substack.com",
    "description": "A newsletter about newsletters.",
    "categoryName": "Business",
    "totalSubscribers": 48211,
    "paidSubscribers": 1203,
    "createdAt": "2022-06-14T09:12:00Z"
}
```

#### Author record

```json
{
    "type": "author",
    "id": 99,
    "name": "Jane Author",
    "handle": "janeauthor",
    "profileUrl": "https://substack.com/@janeauthor",
    "bio": "Writing about media.",
    "photoUrl": "https://.../photo.jpg",
    "publications": [{ "publicationName": "The Example", "subdomain": "example", "role": "admin" }],
    "subscriptions": [{ "publicationName": "Noahpinion", "subdomain": "noahpinion" }]
}
```

#### Comment record

```json
{
    "type": "comment",
    "id": 55512,
    "postId": 123456,
    "postSlug": "why-newsletters-won",
    "postTitle": "Why newsletters won",
    "publication": "example",
    "parentId": null,
    "depth": 0,
    "body": "Great piece.",
    "authorName": "A Reader",
    "authorHandle": "areader",
    "publishedAt": "2026-02-01T16:30:00Z",
    "reactionCount": 4
}
```

### How to scrape Substack (step-by-step)

1. **Click "Try for free"** at the top of this page — you'll be taken to the Apify console.
2. **Paste your target URLs** into the Start URLs field. Examples:
   - A publication: `https://stratechery.com` or `https://noahpinion.substack.com`
   - A single post: `https://example.substack.com/p/some-post`
   - An author profile: `https://substack.com/@handle`
   - A share link: `https://open.substack.com/pub/astralcodexten/p/some-post`
3. **Set `maxPostsPerPublication`** — start with `10` for a test, then bump it (or set `0` for the whole archive).
4. **Click "Start"**. When the run completes, open the **Output** tab to browse results or hit **Export** for CSV / JSON / Excel.

### FAQ

**How am I charged?** Per record in your results — each post, publication, author, and comment counts as one result. Failed or retried requests are never charged, and you'll never receive the same post twice. Control your bill with `maxPostsPerPublication`, `includeComments`, and `maxPublicationsToDiscover`; you can also set a maximum budget for any run in the Apify Console.

**Does it scrape paywalled posts?** Paid posts are listed with metadata and the free preview text; full paid bodies require a subscriber login, which this scraper does not use. Enable `onlyFreePosts` to skip them entirely.

**How many comments will a post produce?** Whatever the thread holds — popular posts can carry hundreds of comments, each delivered (and charged) as its own result. Leave `includeComments` off unless you need them.

**Will it get blocked?** No setup needed on your side — proxy rotation, retries, and rate-limit handling are built in.

**Can I schedule it?** Yes — use Apify Schedules for daily/weekly monitoring runs, and connect the dataset to Google Sheets, webhooks, or the API for delivery.

# Actor input Schema

## `startUrls` (type: `array`):

Substack URLs to scrape: publication homepages (subdomain or custom domain), individual post URLs, author profiles (https://substack.com/@handle), and open.substack.com share links. Leave empty only if you enable Discovery mode below.

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

What to scrape for each publication URL. 'posts' = publication metadata + all posts in the archive. 'publication' = publication metadata only. Post and author URLs are always scraped as posts/authors regardless of this setting ('author' is accepted as an alias of 'publication').

## `maxPostsPerPublication` (type: `integer`):

Limit the number of posts scraped per publication (lower = cheaper runs). Set 0 to scrape the ENTIRE archive — large publications can have thousands of posts. Leaving the field empty uses the default of 50.

## `includeContent` (type: `boolean`):

Fetch each post's full HTML + plain text body. Adds one request per post but gives you the actual article content.

## `includeComments` (type: `boolean`):

Fetch the full comment thread for each post (adds one request per post). Note: every comment becomes a separate result in the dataset, and popular posts can have hundreds of comments.

## `onlyFreePosts` (type: `boolean`):

Skip paid/subscriber-only posts in publication archives (their bodies can't be fully scraped anyway). Post URLs given directly in Start URLs are always scraped.

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

Filter each publication archive by a search term. Only posts matching the term are scraped.

## `discoveryMode` (type: `string`):

Auto-discover publications without providing URLs — seeds from 5 curated top publications and expands through each publication's /recommendations page until the limit below is hit. 'Search' additionally filters every discovered publication's archive by the Discovery query. Off by default: a discovery run scrapes MANY publications and produces a correspondingly large (and more expensive) dataset.

## `discoveryQuery` (type: `string`):

Used with 'Search' Discovery mode: keyword used to filter the archive of each discovered publication. Ignored otherwise.

## `maxPublicationsToDiscover` (type: `integer`):

Cap on how many publications Discovery mode will feed into the scraper (the 5 seed publications count toward it; Start URLs do not). Lower = cheaper runs.

## `maxConcurrency` (type: `integer`):

Parallel requests. Higher = faster runs; proxy rotation is handled automatically, but very aggressive settings can hit Substack rate limits.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://noahpinion.substack.com"
    }
  ],
  "mode": "posts",
  "maxPostsPerPublication": 50,
  "includeContent": true,
  "includeComments": false,
  "onlyFreePosts": false,
  "discoveryMode": "none",
  "discoveryQuery": "AI",
  "maxPublicationsToDiscover": 25,
  "maxConcurrency": 5
}
```

# Actor output Schema

## `results` (type: `string`):

Every scraped record as JSON: posts (full article text, engagement metrics), publications (metadata, subscriber counts), author profiles, and comment threads. Distinguish records by the `type` field.

## `posts` (type: `string`):

Records of type `post`: title, author, publish date, full HTML and plain-text body, word count, reactions, comments, restacks, tags, paywall status.

## `publications` (type: `string`):

Records of type `publication`: name, domain, description, language, subscriber counts (when public), creation date.

## `authors` (type: `string`):

Records of type `author`: name, handle, bio, photo, publications they write for and subscribe to.

## `comments` (type: `string`):

Records of type `comment`: flattened comment threads with body, author, depth, parent id, publish date, and reactions.

# 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 = {
    "startUrls": [
        {
            "url": "https://noahpinion.substack.com"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("doggo/substack-scraper-posts-comments-authors").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 = { "startUrls": [{ "url": "https://noahpinion.substack.com" }] }

# Run the Actor and wait for it to finish
run = client.actor("doggo/substack-scraper-posts-comments-authors").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 '{
  "startUrls": [
    {
      "url": "https://noahpinion.substack.com"
    }
  ]
}' |
apify call doggo/substack-scraper-posts-comments-authors --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=doggo/substack-scraper-posts-comments-authors",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Substack Scraper - posts, comments & authors",
        "description": "Scrape Substack newsletters at scale: full post archives with article text, comments, author profiles, and publication stats like subscriber counts. Works with any Substack URL or custom domain. Fast API-based scraping with no browser, pay per result. Export to CSV, JSON, Excel, or API.",
        "version": "1.1",
        "x-build-id": "UhXzlJf9gcOYL4EWa"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/doggo~substack-scraper-posts-comments-authors/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-doggo-substack-scraper-posts-comments-authors",
                "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/doggo~substack-scraper-posts-comments-authors/runs": {
            "post": {
                "operationId": "runs-sync-doggo-substack-scraper-posts-comments-authors",
                "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/doggo~substack-scraper-posts-comments-authors/run-sync": {
            "post": {
                "operationId": "run-sync-doggo-substack-scraper-posts-comments-authors",
                "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": {
                    "startUrls": {
                        "title": "Start URLs",
                        "type": "array",
                        "description": "Substack URLs to scrape: publication homepages (subdomain or custom domain), individual post URLs, author profiles (https://substack.com/@handle), and open.substack.com share links. Leave empty only if you enable Discovery mode below.",
                        "items": {
                            "type": "object",
                            "required": [
                                "url"
                            ],
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "title": "URL of a web page",
                                    "format": "uri"
                                }
                            }
                        }
                    },
                    "mode": {
                        "title": "Scrape mode",
                        "enum": [
                            "posts",
                            "publication",
                            "author"
                        ],
                        "type": "string",
                        "description": "What to scrape for each publication URL. 'posts' = publication metadata + all posts in the archive. 'publication' = publication metadata only. Post and author URLs are always scraped as posts/authors regardless of this setting ('author' is accepted as an alias of 'publication').",
                        "default": "posts"
                    },
                    "maxPostsPerPublication": {
                        "title": "Max posts per publication",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Limit the number of posts scraped per publication (lower = cheaper runs). Set 0 to scrape the ENTIRE archive — large publications can have thousands of posts. Leaving the field empty uses the default of 50.",
                        "default": 50
                    },
                    "includeContent": {
                        "title": "Include full post content",
                        "type": "boolean",
                        "description": "Fetch each post's full HTML + plain text body. Adds one request per post but gives you the actual article content.",
                        "default": true
                    },
                    "includeComments": {
                        "title": "Include comments",
                        "type": "boolean",
                        "description": "Fetch the full comment thread for each post (adds one request per post). Note: every comment becomes a separate result in the dataset, and popular posts can have hundreds of comments.",
                        "default": false
                    },
                    "onlyFreePosts": {
                        "title": "Only free posts",
                        "type": "boolean",
                        "description": "Skip paid/subscriber-only posts in publication archives (their bodies can't be fully scraped anyway). Post URLs given directly in Start URLs are always scraped.",
                        "default": false
                    },
                    "searchQuery": {
                        "title": "Search query (optional)",
                        "type": "string",
                        "description": "Filter each publication archive by a search term. Only posts matching the term are scraped."
                    },
                    "discoveryMode": {
                        "title": "Discovery mode",
                        "enum": [
                            "none",
                            "leaderboard",
                            "search"
                        ],
                        "type": "string",
                        "description": "Auto-discover publications without providing URLs — seeds from 5 curated top publications and expands through each publication's /recommendations page until the limit below is hit. 'Search' additionally filters every discovered publication's archive by the Discovery query. Off by default: a discovery run scrapes MANY publications and produces a correspondingly large (and more expensive) dataset.",
                        "default": "none"
                    },
                    "discoveryQuery": {
                        "title": "Discovery query",
                        "type": "string",
                        "description": "Used with 'Search' Discovery mode: keyword used to filter the archive of each discovered publication. Ignored otherwise."
                    },
                    "maxPublicationsToDiscover": {
                        "title": "Max publications to discover",
                        "minimum": 1,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Cap on how many publications Discovery mode will feed into the scraper (the 5 seed publications count toward it; Start URLs do not). Lower = cheaper runs.",
                        "default": 25
                    },
                    "maxConcurrency": {
                        "title": "Max concurrency",
                        "minimum": 1,
                        "maximum": 25,
                        "type": "integer",
                        "description": "Parallel requests. Higher = faster runs; proxy rotation is handled automatically, but very aggressive settings can hit Substack rate limits.",
                        "default": 5
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
