Apify
Runs an actor or a saved task in your Apify account and hands its results to the next node — a Google Maps scrape, a website crawl, an Instagram profile, whatever the Store has. For most actors that is one step: run, wait, receive the items. For the slow ones there is a start operation, a status check and a dataset read, which is the polling loop you would otherwise build by hand with three HTTP nodes and a token pasted in each.
Setup
One credential, of type Apify: the API token from Apify Console → Settings → API & Integrations. Add it under Settings → Credentials or straight from the node, then pick it. There is no OAuth — Apify does not offer one to third parties, so Zapier, Make and n8n paste a token too.
Operations
The Operation dropdown decides what the node does and which fields appear under it. These are the exact values the API validates against:
| Value | In the dropdown | Apify call | What it does |
|---|---|---|---|
| runActorAndWait | Run actor and wait | POST /actors/…/run-sync-get-dataset-items | Runs the actor and returns its dataset items in the same step. Waits up to 5 minutes. |
| runTask | Run task and wait | POST /actor-tasks/…/run-sync-get-dataset-items | Same, for a saved task — an actor with its input already set in Apify. Overrides are optional. |
| startRun | Start actor run | POST /actors/…/runs | Starts the actor and returns the run right away: its id, status, defaultDatasetId. Optionally waits up to 60 s first. |
| getRun | Get run | GET /actor-runs/… | The current state of a run — RUNNING, SUCCEEDED, FAILED… This is the check in a polling loop. |
| getDatasetItems | Get dataset items | GET /datasets/…/items | Reads a dataset's items, usually the run's defaultDatasetId. Limit, offset and a field list. |
| getKeyValueRecord | Get key-value record | GET /key-value-stores/…/records/… | One record from a store — the run's OUTPUT, a results map, anything the actor stored by name. |
| abortRun | Abort run | POST /actor-runs/…/abort | Stops a run that is still going. Returns the run with its final state. |
Left out on purpose as operations: listing your actors and datasets, Apify webhooks and the request queue. None of those is needed to run an actor and read what it produced, and the four run/read operations above cover every shape of that. Your actors and tasks are still listed where you set one up — see actorId below.
Configuration
| Field | Operations | What it is |
|---|---|---|
| actorId | runActorAndWait, startRun | Pick it from the list of actors your token has created or run, most recently run first. Typing in the list's search box also searches the Apify Store, so an actor you haven't run yet shows up under Apify Store with how it charges (free, pay per event, pay per result…). You can still type it as username~actor-name (apify~web-scraper, compass~crawler-google-places) or its ID — templates allowed when typed. |
| taskId | runTask | Pick it from your account's saved tasks, or type it as username~task-name or its ID. |
| input | runActorAndWait, startRun, runTask | The actor's input — each actor documents its own. Paste the JSON from the Apify console (Input → JSON) as-is, or write simple fields one per line as field: value. Strings inside may use {{payload.x}}. Empty = the actor's defaults (or, for a task, the task's saved input). |
| limit | the three that return items | How many items to bring into the flow. Empty = all of them — careful with big datasets. |
| clean | the three that return items | Apify's clean flag: drops empty items and fields starting with #. Default Yes. |
| waitForFinishSecs | startRun | 0–60. If the run finishes in time, the returned run already says SUCCEEDED and you can skip the loop. Empty = come back immediately. |
| runId | getRun, abortRun | Usually {{payload.id}} from the Start actor run above it. |
| datasetId | getDatasetItems | Usually {{payload.defaultDatasetId}} from the run. |
| offset, fields | getDatasetItems | Skip the first N items; keep only these comma-separated fields in each item. |
| storeId, recordKey | getKeyValueRecord | The store (usually {{payload.defaultKeyValueStoreId}}) and the record name (OUTPUT). |
| timeoutSecs, memoryMbytes, build | the three that start a run | Advanced. Override the actor's defaults for this run. Empty = the actor's own. |
| gracefully | abortRun | Yes lets the actor finish its current item (Apify waits up to 30 s). Default No. |
Which one you want
Run actor and wait — the one to start with
One node, one step. The node starts the run, follows it until it finishes, and reads its dataset — it hands the items down, marked iterable, so a Loop underneath walks them one by one and a Sheets or Mongo node writes each. Along with the items it hands down the run: runId, status, defaultDatasetId and defaultKeyValueStoreId, so a Get dataset items further down can page through the rest. Most Store actors on a normal input finish well inside the window.
The window is 5 minutes. If the run is still going by then, the node fails with a message that gives its runId and dataset — the run keeps going in Apify, so don't start another: check it with Get run and read it with Get dataset items. A run that ends FAILED, ABORTED or TIMED-OUT fails the node with that status. If an actor regularly needs longer, use the next shape.
Start, check, read — for slow actors
Three operations and a Conditional that loops back, which is the pattern this node was built to replace three raw HTTP calls with:
Webhook
→ Apify "Start" operation: startRun
actorId: compass~crawler-google-places
input: { "searchStringsArray": ["{{payload.query}}"], "maxCrawledPlaces": 200 }
waitForFinishSecs: 60
→ hands down { id, status, defaultDatasetId, defaultKeyValueStoreId, … }
→ Apify "Check" operation: getRun
runId: {{payload.id}}
→ hands down the run again, with its current status
→ Conditional payload.status equals "SUCCEEDED"
✓ → Apify "Read" operation: getDatasetItems
datasetId: {{payload.defaultDatasetId}}
limit: 200
→ hands down { items: [...], count } — iterable
✗ → back to "Check", with "Wait before looping back" set to 30 sTwo details make it work. Get run hands the run down again, so the Conditional reads {{payload.status}} and the read node picks the dataset id straight off the payload — nothing has to be fetched by name. And the loop-back wait lives in the Conditional (Advanced → Wait before looping back), so the check does not hammer Apify; the engine caps the loop at 50 cycles so a run that never finishes cannot spin forever. See Looping back (polling) on the Conditional page.
Put waitForFinishSecs: 60 on the start and the loop often does not even run: if the actor is done within the minute, the first Check already sees SUCCEEDED. For a run gone wrong, add a branch on FAILED or ABORTED so the loop exits instead of waiting for a success that will not come.
Run task and wait
A task is an actor with its input saved in Apify. Use it when the same scrape runs on a schedule and the only thing that changes per event is one or two fields — the Input overrides box merges on top of the saved input, so startUrls: [{ "url": "{{payload.website}}" }] is the whole configuration.
Get key-value record
Some actors do not write a dataset; they store one result under a name in the run's key-value store — OUTPUT is the convention, a screenshot actor stores images. The node reads one record and parses it if it is JSON; text (plain, CSV, XML, HTML) comes back as text with its content type, and anything binary — an image, a PDF — comes back as a file (_file), the same way the HTTP Request node hands down a download, ready to attach or upload. Records larger than 8 MB fail with a message that says so.
Datasets, stores and keys can be picked. Most of the time they come from the flow — the run's defaultDatasetId or defaultKeyValueStoreId — and that is still Use the run's ID from the flow under the list. To read a fixed one, pick it from the list: the named ones by name, the latest runs' by actor and date. Pick a store and its record keys are listed too.
What downstream nodes receive
The node hands its own result to whatever comes next, replacing the payload it was given. After a Run actor and wait, Run task or Get dataset items:
{
"_meta": { "iterable": true, "iterateField": "items", "count": 2 },
"items": [
{ "title": "Niza Restaurante", "totalScore": 4.6, "phone": "+52 …", "website": "http://www.niza.mx/" },
{ "title": "…", "totalScore": 4.2 }
],
"count": 2,
"runId": "ABHqEsz3sjW5Kq7Ye",
"status": "SUCCEEDED",
"defaultDatasetId": "dSyF9Kk3aSqX8Yb2N",
"defaultKeyValueStoreId": "kVrT2Lq8sZfB4Wc1M"
}Iterable over items: a Loop underneath walks them, and a node that writes rows writes one per item. The run fields come with Run actor and wait and Run task, not with Get dataset items. After a Start actor run, Get run or Abort run the run comes down at the root, so its fields are one hop away:
{
"_meta": { "iterable": false, "count": 1 },
"id": "ABHqEsz3sjW5Kq7Ye",
"actId": "nwua9Gu5YrADL7ZDj",
"status": "RUNNING",
"startedAt": "2026-09-13T15:02:11.000Z",
"defaultDatasetId": "dSyF9Kk3aSqX8Yb2N",
"defaultKeyValueStoreId": "kVrT2Lq8sZfB4Wc1M",
"stats": { "…": "…" }
}A Get key-value record hands down { key, contentType, value }, with value parsed when the record is JSON, and a _file instead of value when it is binary.
{{payload.items}} or {{payload.status}}. Anything it needs from the original event it fetches by name — {{$("Webhook").payload.query}} — in a node that supports cross-node references, such as Email, Notification or Code.Example — leads from Google Maps
Webhook "New search" { "query": "restaurantes en Polanco", "max": 50 }
→ Apify "Scrape places" operation: runActorAndWait
actorId: compass~crawler-google-places
input: {
"searchStringsArray": ["{{payload.query}}"],
"maxCrawledPlaces": "{{payload.max}}",
"language": "es"
}
limit: 50
→ hands down { items: [ {title, phone, website, totalScore, …} ], count }
→ Loop walks payload.items, one place per pass
→ Google Sheets append row: {{payload.title}} · {{payload.phone}} · {{payload.website}}{{payload.max}} inside the input is a template in a JSON value. When a value is only a reference — "{{payload.max}}", "{{payload.queries}}" — it lands in the actor's input with the event's own type: a number stays a number and a list a list, even though you write it in quotes. With text around it, or a filter like {{payload.zip | trim}}, it is text — so a zip code like 01234 or a long ID arrives exactly as written. The limit is what enters the flow; the actor's own cap (maxCrawledPlaces) is what it scrapes — set both, or a generous actor fills the run with items you then pay to skip.
AI toolkit mode
Once the credential is picked, the node asks for a Mode. Single operation is everything above: one operation, your templates, every run. AI toolkit turns the node into seven tools that an AI Node — or an MCP client, through one of your MCP servers — calls by name, writing the actor's input and the options per call.
| Tool | Does | Arguments |
|---|---|---|
| run_actor | Runs an actor and waits for its dataset items — Run actor and wait | actor_id · input_json? · limit? · clean? · timeout_secs? · memory_mbytes? · build? |
| start_actor_run | Starts an actor and returns the run without waiting for it — Start actor run | actor_id · input_json? · wait_for_finish_secs? · timeout_secs? · memory_mbytes? · build? |
| run_task | Runs a saved task and waits for its items — Run task and wait | task_id · input_json? · limit? · clean? · timeout_secs? · memory_mbytes? · build? |
| get_run | The status of a run and the IDs of its dataset and store | run_id |
| get_dataset_items | Reads the items of a dataset, a page at a time | dataset_id · limit? · clean? · offset? · fields? |
| get_key_value_record | Reads one record of a key-value store | store_id · record_key |
| abort_run | Stops a run that is still going | run_id · gracefully? |
input_json is the actor's input as a JSON object, written by the model. When the node's Single operation names a fixed actor or task, actor_id and task_id become optional and default to it — the model only names one to run something else.
What you control
Everything below lives in the Settings card of the node's AI Toolkit section — all optional: the defaults work.
- Actors the model can run. Every run spends your credits, so it starts closed: this node's actor + the list below means the actor or task of the Single operation plus the ones you add.
user/name,user~nameand the ID all name the same actor. Any actor lets the model run anything your token reaches. Reading runs, datasets and records is never limited. - Limits. The model decides: runs return 50 items unless it asks for more, up to 200; a run can last up to an hour and use up to 8 GB of memory, and when it doesn't say, the actor's own timeout and memory apply. What you set in Single operation doesn't count in toolkit mode, and the answer says when a request was capped.
- Characters per call sent to the model. 20,000 by default (about 5,000 tokens), anything from 1,000 to 200,000.
What goes back to the model
The same response as the operation. Items that don't fit the characters limit are left out whole — never half an item — and a notes field says how many, so the model can read the rest with get_dataset_items and offset, or ask for fewer fields.run_actor and run_task return the run too — runId and defaultDatasetId — so the model pages through that dataset instead of running the actor again. A limit of 0 or less means the default 50, and input_json must be a JSON object: a list is refused before anything runs. Arguments are used as written: a {{payload.x}} the model writes is not resolved, so it can't read the output of other nodes in the flow.
Testing a tool
operation in their payload that names another tool is refused.{ "operation": "get_dataset_items", "dataset_id": "your-dataset-id", "limit": 5 }Reading costs nothing; run_actor runs the actor for real.
Gotchas
- Running an actor spends Apify credits — from a flow, from Run Test and from an agent in toolkit mode alike. Run Test runs it for real. Point a test at a small input (
maxItems: 5) while you set the node up. - 5 minutes is Apify's ceiling for the synchronous operations, and a 408 does not stop the run — it only stops the wait. Switch to Start + Get run + Get dataset items for slow actors.
waitForFinishSecscaps at 60. That is Apify's maximum for a start call; anything higher is clipped.- An input that is not valid JSON is rejected before anything is called. The message names the problem; nothing runs.
- Run, dataset, store and task IDs belong to the account of the token. Connect a different Apify credential and a saved
runIdmay point at something the new token cannot read — the node says so under the credential. - An empty
limitis all the items, not none. On a 40 000-row dataset that is a 40 000-item payload. - The credential must be
apify. Any other type is refused when the node is created, with the reason.