# Threads Reply Tree Scraper (`devilscrapes/threads-reply-tree`) Actor

Export the full reply tree of any public Threads post. No Meta login. Conversation graph plus engagement counts via the threads.net SSR HTML payload.

- **URL**: https://apify.com/devilscrapes/threads-reply-tree.md
- **Developed by:** [DevilScrapes](https://apify.com/devilscrapes) (community)
- **Categories:** Social media
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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

<img src=".actor/icon.svg" width="160" alt="Threads Reply Tree Scraper" />

## Threads Reply Tree Scraper

_We do the dirty work so your dataset stays clean._ 😈

**$5.05 / 1,000 rows** — Export the full reply tree of any public Threads (`threads.net`) post. No Meta account. No API key. Get every visible reply chain, depth-linked, with engagement counts on every node, ready for conversation-graph analysis.

Existing Threads scrapers on the Apify Store cap at ~20 posts per profile with no reply-tree expansion. This Actor goes the opposite direction: pick one post, get the whole conversation underneath it.

### 🎯 What this scrapes
You pass one or more Threads post URLs. For each post, this Actor:

1. Fetches `https://www.threads.net/@{username}/post/{code}` with a real browser fingerprint (`curl-cffi` Chrome 131 TLS + H2 impersonation).
2. Extracts the server-rendered conversation payload Threads embeds inside `<script type="application/json" data-sjs>` blocks.
3. Walks the payload's `edges -> thread_items` tree and emits one flat row per node — the root post plus every reply Threads inlined into the initial HTML, including nested chains (depth 2+).

Every row carries a `row_type` discriminator (`"post"` for the root, `"reply"` for everything else), a `depth` integer (`0` for root, `1` for direct replies, `2+` for nested chain replies), and a `parent_reply_id` pointer so consumers can reconstruct the conversation graph with a single `LEFT JOIN`.

| Field | Type | Description |
|---|---|---|
| `row_type` | string enum | `"post"` for the root, `"reply"` for everything else |
| `root_post_id` | string | Threads `pk` of the input post this row belongs to |
| `root_post_url` | string | Input URL (normalized) — same value on every row from one input |
| `parent_reply_id` | string \| null | `null` for root; root `pk` for direct replies; predecessor `pk` for nested |
| `reply_id` | string | This node's `pk` |
| `reply_url` | string | Public Threads URL of this node |
| `reply_text` | string | Caption body (empty string if media-only) |
| `author_username` | string | Author handle |
| `author_display_name` | string \| null | Author full name |
| `author_user_id` | string \| null | Internal Threads user `pk` |
| `author_followers` | integer \| null | Follower count when Threads surfaces it (usually only root author) |
| `posted_at` | string | ISO 8601 UTC timestamp |
| `like_count` | integer | Likes at scrape time |
| `reply_count` | integer | Direct reply count at scrape time |
| `repost_count` | integer | Repost count at scrape time |
| `quote_count` | integer | Quote-post count at scrape time |
| `depth` | integer | `0`=root, `1`=direct, `2+`=nested chain |
| `scraped_at` | string | ISO 8601 UTC when the row was written |

### 🔥 Features
- No Meta account needed — uses public `threads.net` SSR HTML; no login, no API key, no OAuth.
- Full reply tree per post — root + every reply chain Threads server-renders into the initial HTML.
- Depth-linked output — `depth` + `parent_reply_id` let you rebuild the conversation graph trivially in SQL, pandas, or networkx.
- Engagement counts on every node — likes, direct replies, reposts, quote-posts captured per post and per reply.
- Per-post cost control via `maxDepth` (1–10) and `maxRepliesPerNode` (1–500) caps.
- Real Chrome 131 TLS + H2 fingerprint via `curl-cffi` impersonation — survives Meta's basic fingerprint checks.
- Residential proxy (BUYPROXIES94952) ON by default — Meta blocks datacenter IPs aggressively.
- Pydantic v2 input validation — bad URLs, empty lists, and out-of-range caps fail fast before any network call.
- Apache-2.0 licensed; source code style locked by Devil Scrapes ADR-0003 (SRP, ≤40-line functions, no magic values).

### 💡 Use cases
- **Brand reputation monitoring** — pull the entire reply pile-on under a viral mention of your brand and triage by like count or top-level reach.
- **Social-listening dashboards** — feed conversation-graph rows into Slack, Looker, Tableau, or Hex for real-time sentiment analysis on Threads.
- **Meta-policy research** — measure conversation topology on policy-adjacent posts (e.g. how often does a public official's post attract nested debate sub-threads?).
- **Creator analytics** — see which of your own replies sparked sub-conversations vs which died after one comment.
- **Crisis comms** — quickly download every visible reply to a controversial post for PR review, without manual scrolling.
- **Academic research** — bootstrap conversation-tree datasets for NLP / argument-mining models from public Threads discussions.
- **Competitive intelligence** — track reply sentiment under competitor product launches on Threads.

### ⚙️ How to use it
1. Open the Actor input form.
2. Paste one or more Threads post URLs into **Threads post URLs** — e.g. `https://www.threads.net/@mosseri/post/DYX3oNcAO4r`. Up to 50 URLs per run.
3. Set **Maximum reply depth** to control how deep into nested chains the Actor goes (default `3`).
4. Set **Max top-level reply threads per post** to cap how many direct replies are exported per post (default `50`).
5. Leave **Use Apify Proxy** ON unless you have a specific reason to disable it — Meta blocks datacenter IPs within minutes.
6. Click **Start**. Results stream into the default dataset in real time and are downloadable as JSON, CSV, Excel, or XML.

#### Finding a Threads post URL

Open any public post on `threads.net` or in the Threads app and copy the link. The URL format is `https://www.threads.net/@{username}/post/{code}`. Trailing query strings (`?xmt=...`) and fragments (`#...`) are stripped automatically — paste the raw share URL straight in.

### 📥 Input
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `postUrls` | array of strings | yes | — | 1–50 Threads post URLs |
| `maxDepth` | integer | no | `3` | Reply-depth cap (1–10) |
| `maxRepliesPerNode` | integer | no | `50` | Top-level reply cap per post (1–500) |
| `useProxy` | boolean | no | `true` | Route via BUYPROXIES94952 residential |

#### Single-URL example

```json
{
  "postUrls": [
    "https://www.threads.net/@mosseri/post/DYX3oNcAO4r"
  ],
  "maxDepth": 3,
  "maxRepliesPerNode": 50,
  "useProxy": true
}
````

#### Batch example

```json
{
  "postUrls": [
    "https://www.threads.net/@mosseri/post/DYX3oNcAO4r",
    "https://www.threads.net/@threads/post/AAA",
    "https://www.threads.net/@zuck/post/BBB"
  ],
  "maxDepth": 2,
  "maxRepliesPerNode": 25,
  "useProxy": true
}
```

### 📤 Output

One flat dataset row per post or reply. Use `row_type` to filter to roots only, or `depth` to filter to direct replies, top-level threads, or specific nested layers.

```json
{
  "row_type": "post",
  "root_post_id": "3897828658278100523",
  "root_post_url": "https://www.threads.net/@mosseri/post/DYX3oNcAO4r",
  "parent_reply_id": null,
  "reply_id": "3897828658278100523",
  "reply_url": "https://www.threads.net/@mosseri/post/DYX3oNcAO4r",
  "reply_text": "Does DMing people back help with reach?",
  "author_username": "mosseri",
  "author_display_name": "Adam Mosseri",
  "author_user_id": "63482099442",
  "author_followers": null,
  "posted_at": "2026-05-15T13:36:48+00:00",
  "like_count": 427,
  "reply_count": 98,
  "repost_count": 12,
  "quote_count": 2,
  "depth": 0,
  "scraped_at": "2026-05-16T12:00:00+00:00"
}
```

#### Export formats

After a run completes, click **Export** in the Apify Console for JSON (full fidelity), CSV (flat — ideal for spreadsheets), Excel (`.xlsx`), or XML. All formats are available via `GET /datasets/{id}/items?format=csv&clean=true` on the Apify REST API.

#### Reconstructing the conversation tree

In SQL:

```sql
SELECT parent.reply_text  AS parent_text,
       child.reply_text   AS reply_text,
       child.depth,
       child.like_count
FROM   rows child
LEFT JOIN rows parent
  ON   child.parent_reply_id = parent.reply_id
WHERE  child.root_post_id = '3897828658278100523'
ORDER BY child.depth, child.like_count DESC;
```

In pandas: `df.merge(df, left_on="parent_reply_id", right_on="reply_id", suffixes=("", "_parent"))`.

### 💰 Pricing

Pay-Per-Event (PPE) — you pay only for what you scrape.

| Event | Price (USD) | When |
|---|---|---|
| `actor-start` | $0.05 | Once per run, at boot |
| `result-row` | $0.005 | Per post or reply row written |

#### Example costs

| Rows scraped | Actor starts | Total cost |
|---|---|---|
| 100 | 1 | $0.55 |
| 500 | 1 | $2.55 |
| 1,000 | 1 | $5.05 |
| 5,000 | 1 | $25.05 |

A typical run on a single mid-sized post (root + ~50 direct replies + a handful of nested chains) emits 60–120 rows, costing $0.35–$0.65.

### 🚧 Limitations

- **No "Show replies" pagination.** Threads renders some deeply nested replies behind a "Show replies" click that triggers a client-side XHR. This Actor emits exactly what `threads.net` serves in the initial HTML — typically the root, all direct replies, and any inline-expanded depth-2/3 chains Threads already included. Deeper hidden replies require their own click and are not fetched.
- **No reposter user list.** Threads renders the `/reposts/` sub-page entirely client-side from a private GraphQL endpoint that uses rotating `doc_id` + `lsd` tokens. Repost *counts* are captured on every row (`repost_count`), but the list of accounts that reposted is out of scope.
- **No quote-post bodies.** `quote_count` is captured per row; the bodies of quote-posts referencing the input would require additional fetches and are not included.
- **No media (images, videos).** Only `reply_text` is captured. Image ALT text, video transcripts, and external link cards are not extracted.
- **Private profiles / login-walled posts return zero rows.** If Threads serves a login wall (depending on IP reputation), the Actor logs a WARNING and skips that URL. Enable `useProxy` to maximise success rate.
- **Meta may rate-limit.** With residential proxy + per-URL session rotation the Actor handles single-post scrapes reliably. Very large batches (>20 posts in one run) may trigger short rate-limit windows — the Actor retries with exponential backoff up to 5 attempts per URL.
- **Apify FREE plan retains run-scoped storage for 7 days only.** Export your dataset immediately after the run or use a named dataset to retain longer.
- **ToS responsibility.** Meta's Terms of Service prohibit scraping. The `threads.net` post URL is publicly accessible without login, but you remain responsible for verifying your jurisdiction's data-protection rules and Meta's current Terms before using scraped data commercially.

### ❓ FAQ

**Do I need a Threads or Instagram account?**

No. The Actor calls `threads.net` directly with a real Chrome 131 fingerprint. No Meta login, no API key, no OAuth.

**Does this work for any public Threads post?**

Yes, as long as the post is reachable at its public URL without a login wall. Private accounts, deleted posts, and posts behind an age-gate return zero rows and a clear status message.

**How deep into the reply tree does this go?**

By default, depth `3` — root post (depth 0), direct replies (depth 1), and the first two layers of inline-expanded nested replies Threads embeds in the initial HTML (depth 2 and 3). Increase `maxDepth` up to `10` if you need every embedded chain.

**Why isn't the reposter list included?**

Threads' `/reposts/` sub-page loads its user list via an internal client-side XHR that uses rotating GraphQL `doc_id` + `lsd` tokens. Implementing that would create constant breakage as Meta rotates the tokens. Repost *counts* are still captured on every row.

**Why is `useProxy` ON by default?**

Meta blocks repeated requests from the same datacenter IP within minutes. The Devil Scrapes BUYPROXIES94952 residential pool rotates IPs per URL, which is the difference between consistent success and an empty dataset.

**Can I rebuild the conversation graph?**

Yes — every row carries `parent_reply_id`, so a single `LEFT JOIN` on `reply_id` reconstructs the tree. See the **Output → Reconstructing the conversation tree** section above for SQL and pandas examples.

**What happens if Meta blocks the request?**

The Actor retries with exponential backoff (up to 5 attempts per URL). If all retries fail or the page returns a login wall instead of the conversation payload, that URL is skipped with a WARNING log and the run continues with the next URL. If every URL fails, the Actor exits non-zero with a clear status message.

### 💬 Your feedback

Found a bug, hit a rate-limit pattern, or need a new field on the output row? Open an issue on the Actor's Apify Store page or contact the Devil Scrapes team at [apify.com/DevilScrapes](https://apify.com/DevilScrapes). We ship updates within days of validated reports.

# Actor input Schema

## `postUrls` (type: `array`):

List of one or more public Threads post URLs of the form <code>https://www.threads.net/@{username}/post/{code}</code>. Up to 50 URLs per run.

## `maxDepth` (type: `integer`):

Cap on reply depth emitted. <code>1</code> = direct replies only; <code>2</code> = include inline-expanded depth-2 replies; <code>3</code> (default) covers the typical Threads conversation tree.

## `maxRepliesPerNode` (type: `integer`):

Cap on the number of top-level reply threads exported per post. Default 50.

## `useProxy` (type: `boolean`):

Route requests through Apify Proxy (BUYPROXIES94952 residential). Recommended ON — Meta blocks datacenter IPs aggressively.

## Actor input object example

```json
{
  "postUrls": [
    "https://www.threads.net/@mosseri/post/DYX3oNcAO4r"
  ],
  "maxDepth": 3,
  "maxRepliesPerNode": 50,
  "useProxy": true
}
```

# Actor output Schema

## `datasetItems` (type: `string`):

All dataset items as JSON.

## `datasetItemsCsv` (type: `string`):

Same data exported to CSV.

## `datasetView` (type: `string`):

Open the run dataset in the Console.

# 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 = {
    "postUrls": [
        "https://www.threads.net/@mosseri/post/DYX3oNcAO4r"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("devilscrapes/threads-reply-tree").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 = { "postUrls": ["https://www.threads.net/@mosseri/post/DYX3oNcAO4r"] }

# Run the Actor and wait for it to finish
run = client.actor("devilscrapes/threads-reply-tree").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 '{
  "postUrls": [
    "https://www.threads.net/@mosseri/post/DYX3oNcAO4r"
  ]
}' |
apify call devilscrapes/threads-reply-tree --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=devilscrapes/threads-reply-tree",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Threads Reply Tree Scraper",
        "description": "Export the full reply tree of any public Threads post. No Meta login. Conversation graph plus engagement counts via the threads.net SSR HTML payload.",
        "version": "0.1",
        "x-build-id": "sLd9ZlHcBQCWliWcf"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/devilscrapes~threads-reply-tree/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-devilscrapes-threads-reply-tree",
                "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/devilscrapes~threads-reply-tree/runs": {
            "post": {
                "operationId": "runs-sync-devilscrapes-threads-reply-tree",
                "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/devilscrapes~threads-reply-tree/run-sync": {
            "post": {
                "operationId": "run-sync-devilscrapes-threads-reply-tree",
                "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",
                "required": [
                    "postUrls"
                ],
                "properties": {
                    "postUrls": {
                        "title": "Threads post URLs",
                        "type": "array",
                        "description": "List of one or more public Threads post URLs of the form <code>https://www.threads.net/@{username}/post/{code}</code>. Up to 50 URLs per run.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxDepth": {
                        "title": "Maximum reply depth",
                        "minimum": 1,
                        "maximum": 10,
                        "type": "integer",
                        "description": "Cap on reply depth emitted. <code>1</code> = direct replies only; <code>2</code> = include inline-expanded depth-2 replies; <code>3</code> (default) covers the typical Threads conversation tree.",
                        "default": 3
                    },
                    "maxRepliesPerNode": {
                        "title": "Max top-level reply threads per post",
                        "minimum": 1,
                        "maximum": 500,
                        "type": "integer",
                        "description": "Cap on the number of top-level reply threads exported per post. Default 50.",
                        "default": 50
                    },
                    "useProxy": {
                        "title": "Use Apify Proxy (residential)",
                        "type": "boolean",
                        "description": "Route requests through Apify Proxy (BUYPROXIES94952 residential). Recommended ON — Meta blocks datacenter IPs aggressively.",
                        "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
