The Scrap object is the same shape wherever you read it — REST response, MCP trawl_get_scrap tool, web app, webhook correlation. This guide documents the fields you can rely on.
History rows (individual runs) have their own shape, covered at the bottom of this page.
Where you encounter it
| Surface | Returns |
|---|---|
GET /api/scraps/:id (REST, API key) |
Full Scrap with recent history id list |
trawl_get_scrap (MCP) |
Public fields only — encrypted account blobs never leave the server |
trawl_get_scrap_history (MCP) |
Array of History rows for one scrap |
| Webhook payload | Compact event shape carrying scrapId + historyId — fetch the full objects via REST or MCP |
Scrap fields
| Field | Type | Notes |
|---|---|---|
id |
string | 24-char hex ObjectId |
title |
string | Display name |
description |
string | Free-form |
url |
string | Target URL. Exposed to the script as TRAWL.url. Immutable at run time |
request |
string | Puppeteer script body — must call returnData(array) |
scrapper |
string | Engine id (defaults puppeteer) |
containers |
string[] | Worker ids. Auto-assigned from the org default when omitted on create |
params |
object[] | Parameter sets ([{ key, value }]). One is picked at random on cron runs |
history |
string[] | Most recent execution ids (capped at 50, most recent first) |
cron |
string | null | Cron expression (null = manual only). See Schedule |
cronTimezone |
string | IANA timezone. Defaults UTC |
alert |
string | null | Email notified on alert conditions |
autoFix |
boolean | Whether AI Fix is enabled for this scrap |
proxyTier |
string | null | tier0 … tier4 (see Scraping Advanced) |
lastTierChangeAt |
ISO-8601 | null | Server-managed, read-only. Stamped on every non-tier0 run |
emailNotif |
boolean | Email results after cron runs |
emailNotifRecipient |
string | null | Where to send results |
emailNotifFormat |
"json" | "csv" |
Result attachment format |
digestEnabled |
boolean | AI Digest summary on top of the result email |
digestPrompt |
string | null | Digest instructions (see AI Features) |
digestRecipient |
string | null | Digest email target |
banner |
string | Upload path for the scrap banner image |
user |
string | Owner user id |
organizationId |
string | Owning organization |
createdAt / updatedAt |
ISO-8601 | Timestamps |
Example
{
"id": "507f1f77bcf86cd799439011",
"title": "Hacker News — AI search",
"url": "https://news.ycombinator.com/search",
"request": "var page = await browser.newPage(); await page.goto(`${TRAWL.url}?q=${TRAWL.query}`); …",
"containers": ["64a1f2e3b5c6d7e8f9a0b1c2"],
"params": [{ "key": "query", "value": "AI tools 2026" }],
"cron": "0 9 * * 1",
"cronTimezone": "Europe/Paris",
"autoFix": true,
"proxyTier": "tier1",
"emailNotif": true,
"emailNotifFormat": "csv",
"digestEnabled": false,
"history": ["65a0…", "65a1…"],
"user": "507f1f77bcf86cd799439011",
"organizationId": "507f1f77bcf86cd799439012",
"createdAt": "2026-03-01T08:00:00.000Z",
"updatedAt": "2026-04-17T10:00:00.000Z"
}What never leaves the server
request.datain full — only a truncatedresultPreviewships via webhooks; the full result lives on the history row behind auth- Encrypted
account.username/account.password/account.session.cookies— decrypted inside the worker only - Any field not listed in the table above
History row fields
A History row is one run of a scrap. You get them from GET /api/historys?scrap=<id>, the MCP trawl_get_scrap_history tool, or a GET /api/historys/:historyId lookup after a webhook delivery.
| Field | Type | Notes |
|---|---|---|
id |
string | Row id — matches historyId in webhook payloads |
scrap |
ObjectId | Parent scrap id |
organizationId |
ObjectId | Owning organization |
status |
boolean | null | Tri-state outcome: true = success, false = failure, null = pending/in-flight |
statusDetail |
"success" | "error" | "empty" | "regression" | null |
Fine-grained state: success (data returned), error (script threw), empty (0 items), regression (count drop) |
data |
string | JSON-encoded result array. Parse client-side |
length |
number | Count of items in data |
time |
number | Worker duration (ms) |
digest |
string | null | AI-generated markdown digest text (if enabled) — plain string, not an object |
triggeredBy |
"user" | "api" | "cron" |
What started the run |
type |
"scrap_run" | "ai_wizard" | "ai_generate" |
Row type — AI ops appear as standalone rows |
proxyTier |
string | Which tier actually ran |
bytesTransferred |
number | Payload size tracked for billing |
totalCost |
number | Total micro-credits billed for this run |
aiCost / fixAiCost / proxyCost / captchaCost |
number | Per-dimension cost breakdown |
fixVersionId |
string | null | When the row was produced by an AI Fix re-run, points to the applied version |
fixedAt |
ISO-8601 | null | When AI Fix amended this row |
errorSnapshot |
object | null | Page HTML + selector + screenshot captured on failure (admin UI only) |
retries |
number | Worker-side retry count |
Cost contract
Billing fields (totalCost, *Cost, bytesTransferred, priced) are present on every row but only meaningful to the owner and admins. API-key responses include them by default; the web app cost dashboard aggregates from the same source.
See also: API Keys · MCP Server · Webhooks · Data Quality
Next step → API keys