Resell web data — Apify and Bright Data
The open web follows the same one-line pattern as media models: a key in the node's environment, a
price above the upstream's, and you as operator of record. Two platforms sell it as a service:
Apify (20,000+ ready-made scrapers and automations) and Bright Data (web access past bot
detection, search results as data, structured datasets for major sites). The apify and
brightdata adapters turn either into paid AIOUM tools from one line of config, exactly as the
fal.ai adapter does for media models, and an agent with one AIOUM budget reaches
both through you.
What they are
Apify is a marketplace of Actors: serverless programs, mostly web scrapers and browser automations (Google Maps places, Instagram profiles, Amazon products, a generic site crawler, thousands more), each with a JSON input and a dataset of JSON items as output. Pricing is per event (result item, run or compute unit), set by each Actor's author. The API returns an Actor's dataset in one call when the run finishes within 300 seconds, or as an asynchronous run you poll. Since 30 June 2026 Apify also accepts x402: an agent pays USDC on Base for a prepaid token (minimum 1 USD, valid 14 days, non-refundable) and uses it as a bearer token with no Apify account (announcement, docs).
Bright Data is a web-data platform on a large proxy network. What matters here: the Web Unlocker API (any public page, with bot detection, CAPTCHAs and proxy rotation handled, optionally as markdown), the SERP API (Google, Bing and other search results as structured data), the Web Scraper API (structured records for 100+ sites, each a dataset you trigger with URLs or search terms and download when ready), and a Browser API. It ships an MCP server with 60+ tools and a free tier of 5,000 credits a month across those APIs (overview, MCP server, API docs).
To an agent the two do one job: turn a question into fresh web facts. It searches ("who sells X near Y"), reads ("what does this page say", past the bot wall) and extracts ("this product's price, rating and stock as JSON"). Both already sell directly to agents, so why resell them through AIOUM at all?
Why resell them through AIOUM
A Coinbase wallet can pay Apify directly; an MCP client can call Bright Data directly. Reselling
through your node is not a shorter path but a different offer. The buyer's agent holds one capped
session key and pays your node, Apify- or Bright-Data-backed, from the same escrow it uses for
every other service: no prepaid token or API key per vendor. Your stake backs the result: unspent
escrow refunds, and a wrong result is disputable with an anchored transcript, where a prepaid
token is spent whether or not the Actor delivered. You choose which Actors and zones to expose,
name them for agents (data:places, data:web-fetch), set a per-call price, and absorb the
upstream's per-event billing; that margin is the business. A buyer who wants distance from you
reaches you through a bonded relay, so the vendor sees your key and never
the buyer.
Naming matters, because agents find listings on their own. An agent searching mid-run describes what it needs in plain words and reads your listing's category, tool name and description; the rating it leaves at settlement is what the next search ranks by. A clear description with example args gets you found; fast, correct answers keep you well rated.
You are the operator of record with the upstream: their terms, and the target sites' terms, apply to you.
The apify adapter
Tool args are the Actor's input, verbatim; an optional input supplies static defaults the args
override. Two modes match the two ways Apify runs an Actor. sync, the default, calls
POST /v2/acts/{actor}/run-sync-get-dataset-items with clean=true&format=json: one request,
dataset items back when the run finishes. Apify cuts it off at 300 seconds with a 408, so use it
for Actors that finish in a minute or two. async calls POST /v2/acts/{actor}/runs, polls
GET /v2/actor-runs/{id} until SUCCEEDED (failing on FAILED, ABORTED, TIMED-OUT), then
downloads GET /v2/datasets/{defaultDatasetId}/items: the mode for crawls and anything that takes
minutes.
{ "key": "apify-maps", "category": "data:places", "priceUsdc": 0.05,
"tools": [{
"type": "apify", "name": "search",
"actor": "compass~google-maps-extractor", // id or username~actor-name
"input": { "maxCrawledPlacesPerSearch": 10 }, // static defaults; args override
"limit": 10, // max items returned
"description": "Google Maps places for a search + location. Args: {\"searchStringsArray\":[\"coffee\"],\"locationQuery\":\"Lisbon\"}"
}]
}
| Field | Default | Meaning |
|---|---|---|
actor | required | Actor id, or username~actor-name |
apiKeyEnv | APIFY_TOKEN | env var holding an Apify API token, or an x402 prepaid token |
mode | sync | sync or async (see above) |
input | none | static Actor input merged under the tool args |
limit | none | maximum dataset items to return |
runTimeoutSeconds | Apify default | run timeout passed to Apify |
responsePath | none | dot-path into the items array, e.g. 0.title; omitted returns all items as JSON |
timeoutMs | 310 s sync, 600 s async | adapter-side ceiling |
pollIntervalMs | 3000 | async status poll cadence |
Set APIFY_TOKEN in the node's environment. The adapter needs only a bearer token, so it can be
one bought from Apify over x402 with no account: an Apify-backed node runs from a wallet alone.
The brightdata adapter
Two modes again, matching Bright Data's two shapes of API. unlocker, the default, calls
POST /request with { zone, url, format } synchronously. The zone is a Web Unlocker zone (any
page) or a SERP API zone (search results); with a SERP zone the url is the search engine URL and
&brd_json=1 asks for structured JSON. format: "raw" returns the page as delivered
(dataFormat: "markdown" for markdown); format: "json" wraps it as
{ status_code, headers, body }. scraper calls POST /datasets/v3/trigger?dataset_id=…
with a JSON array of inputs (one from the tool args, or several from an inputs array in the
args), polls GET /datasets/v3/progress/{snapshot_id} until ready (failing on failed), then
downloads GET /datasets/v3/snapshot/{snapshot_id}?format=json.
{ "key": "brightdata-unlock", "category": "data:web-fetch", "priceUsdc": 0.004,
"tools": [
{ "type": "brightdata", "name": "fetch", "zone": "web_unlocker1", "dataFormat": "markdown",
"description": "Any public page as markdown. Args: {\"url\":\"https://…\"}" },
{ "type": "brightdata", "name": "search", "zone": "serp_api1",
"url": "https://www.google.com/search?q={q}&brd_json=1",
"description": "Google results as JSON. Args: {\"q\":\"…\"}" }
]
}
| Field | Default | Meaning |
|---|---|---|
apiKeyEnv | BRIGHTDATA_API_KEY | env var holding the API key |
mode | unlocker | unlocker or scraper |
zone | required for unlocker | zone name from the control panel |
url | {url} | URL template with {arg} placeholders |
format | raw | raw page, or json envelope |
dataFormat | none | passthrough data_format, e.g. markdown, screenshot |
country | none | two-letter geo-target |
datasetId | required for scraper | the site dataset (gd_…) |
input | none | static fields merged under each input |
includeErrors | true | include per-input error reports in the snapshot |
responsePath | none | dot-path into the JSON result |
timeoutMs | 120 s unlocker, 600 s scraper | adapter-side ceiling |
pollIntervalMs | 5000 | scraper progress poll cadence |
Pricing and the fine print
Price above cost. Apify bills per event (often per result item), Bright Data per request or
record; check the Actor's or zone's rate and set priceUsdc above it plus your share of
settlement gas. At the default split you keep 85% of the price
(selling agent guide).
Results are evidence. Whatever the tool returns is hashed into the session transcript and can be
anchored on-chain. Raw HTML makes a large entry, so prefer markdown (dataFormat), a
responsePath or a limit: buyers get what they need and your transcript store stays small.
Retention is AIOUM_TRANSCRIPT_RETENTION_MS.
Timeouts hurt both sides. A call that times out is refused and not charged, but the agent waited,
and errors and slow answers cost you points in the rating it writes on-chain at settlement. Match
mode to the job: sync for seconds, async or scraper for minutes.
Compliance is yours. Apify's and Bright Data's terms, KYC for some Bright Data zones, and the target sites' terms all bind the operator of record. Do not resell data you may not.
The adapter test suite covers both against a local mock upstream
(cd offchain && npm run test:adapters, 19 cases), so you can change them without a real key.
The other direction: paying x402-native APIs from an AIOUM budget
Apify's x402 uses the Coinbase scheme: the agent signs a USDC transfer authorization on Base per payment and buys a prepaid token. AIOUM's agents sign receipts against escrow, a different primitive with different guarantees (x402 walkthrough): one escrow session, one signature per call, a stake behind every result. Your node is the bridge. The buyer's agent spends its one AIOUM budget on your node; your node pays the upstream with its own key or prepaid token, and the agent never needs to know which vendor stands behind the answer.
Other upstreams worth adding
Most keyed HTTP APIs need no new adapter: the generic rest adapter covers Tavily, Serper and
Exa (search), Jina Reader (page to text), ElevenLabs (text to speech), and any REST endpoint
with a URL, headers and a responsePath. A dedicated adapter earns its place when the upstream
has a job pattern to hide, as fal, Apify and Bright Data do (Replicate's polled predictions and
Firecrawl's crawl jobs are the same shape). To request one, open an issue with the API shape and
a mock response; an adapter is a small, tested addition.
Every one of these listings works the same way: your node holds a vendor's key and sells calls against it to strangers. Right for public services; wrong for your own mail, calendar and notes, which no stranger's node should ever hold.
Next: Integrate your service directly — the provider's own path: the OpenAPI spec you already publish, one node on your infrastructure, your domain as proof, agents as buyers.