AI Code Runner Sandbox avatar

AI Code Runner Sandbox

Pricing

from $0.39 / 1,000 code executions

Go to Apify Store
AI Code Runner Sandbox

AI Code Runner Sandbox

Run JavaScript or Python code in an isolated sandbox. Pass data via stdin, capture stdout and stderr, parse JSON output, save generated files, and get one structured execution record with a wall timeout and output caps.

Pricing

from $0.39 / 1,000 code executions

Rating

0.0

(0)

Developer

ParseBird

ParseBird

Maintained by Community

Actor stats

1

Bookmarked

1

Total users

1

Monthly active users

7 days ago

Last modified

Categories

Share

AI Code Runner Sandbox

AI Code Runner Sandbox runs a JavaScript or Python code snippet in an isolated, throwaway sandbox and returns one structured execution record. Send data in through standard input, read the result from standard output, and get back the exit code, captured stdout/stderr, timing, and any files the snippet generated. It is a code execution API for AI agents, automation workflows, and data pipelines that need to run a small piece of code without hosting a runtime.

Run JavaScript (Node.js 22) or Python 3 code up to 100 KB — pass a JSON value or string on stdin, cap the wall time (1–30s) and output size, parse stdout into a JSON result, and preserve up to 10 generated files. One deterministic execution record per run, success or failure.

Copy to your AI assistant

Copy this block into ChatGPT, Claude, Cursor, or any LLM to start using this actor.

Actor: parsebird/code-runner-sandbox (AI Code Runner Sandbox on Apify)
Purpose: run one JavaScript or Python snippet in an isolated sandbox and return a structured execution record.
Call it with ApifyClient. Example (Python):
from apify_client import ApifyClient
client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("parsebird/code-runner-sandbox").call(run_input={
"language": "python", # "javascript" (default) or "python"
"code": "import sys, json\ndata = json.load(sys.stdin)\nprint(json.dumps({'total': sum(data['values'])}))",
"stdin": '{"values": [3, 5, 8]}', # text written to stdin; enter JSON and parse it in the snippet; optional
"parseJsonOutput": True, # parse stdout into `result`; default true
"timeoutSeconds": 5, # wall-clock limit, 1..30; default 5
"maxOutputBytes": 256000, # combined stdout+stderr cap, max 1048576
"saveFiles": [], # up to 10 relative paths to keep in the key-value store
"maxSavedFileBytes": 5000000 # combined saved-file cap, max 10485760
})
record = next(client.dataset(run["defaultDatasetId"]).iterate_items())
Output record fields: status ("succeeded"|"failed"|"timed_out"), language, exitCode, signal, stdout, stderr,
durationMs, timedOut, outputTruncated, terminationReason, result, resultParseError, files, executedAt.
Always check `status` and `exitCode` before trusting `result`. User-code errors still return a record;
only invalid requests (missing code, bad limits, oversized source) fail the Actor run.
API docs: https://docs.apify.com/api/v2 | Token: https://console.apify.com/account/integrations

What does AI Code Runner Sandbox do?

The Actor writes your snippet to a fresh temporary directory and runs it under a dedicated unprivileged user. It captures the output streams, enforces resource limits, collects requested files, and produces a single execution record for every run — regardless of whether the code succeeded or threw.

  • 🟨 Two runtimesjavascript runs on Node.js 22 as an ES module (import, top-level await), python runs on Python 3. Pick per run.
  • 📥 stdin — pass any text (enter JSON and parse it in your snippet). The snippet reads it from standard input.
  • 📤 JSON result parsing — when parseJsonOutput is on, the complete standard output is parsed into a result field so downstream steps get typed data, not a string.
  • ⏱️ Wall-clock timeout — 1 to 30 seconds. On expiry the whole detached process group is signalled and force-killed, so child processes stop too.
  • 📏 Output caps — a combined stdout + stderr limit up to 1 MB. When reached, capture stops, outputTruncated is set, and terminationReason is "output_limit".
  • 📎 File capture — list up to 10 relative paths the snippet writes; each is stored in the run's key-value store and referenced in files, within a combined size cap.
  • 🧾 Deterministic recordstatus, exitCode, signal, durationMs, timedOut, outputTruncated, terminationReason, result, resultParseError, files, and executedAt on every run.
  • 🔌 Platform-native — schedule runs, call it from the Apify API, chain it in task workflows, trigger it from integrations (Zapier, Make, n8n, GitHub, Slack), and export records as JSON, CSV, or Excel.

Keep first runs small. A 5-second timeout and no generated files are enough for most transformations — validating JSON, reshaping a payload, computing a score, or generating a compact CSV.

What can you do with AI Code Runner Sandbox?

  • AI agents and MCP — let an agent execute a computed step: validate its own JSON output against constraints, calculate metrics, or reshape data between tool calls, then read the typed result.
  • n8n, Make, and Zapier workflows — run a transformation that is awkward to express in visual nodes without standing up a serverless function.
  • Data teams — apply a Python calculation or a JavaScript normalization pass to a webhook payload or an API response.
  • Developers and QA — reproduce an algorithm, test an AI-generated function against fixed inputs, or check behavior in a clean environment.
  • Scheduled jobs — run a small script on a cron schedule and keep every execution record for auditing.

Input parameters

ParameterTypeRequiredDefaultDescription
codestringYesSource code to execute, up to 100 KB. Read from stdin, print the result to stdout.
languagestringNojavascriptRuntime for the snippet: javascript (Node.js 22) or python (Python 3).
stdinstringNoomittedText written to standard input. Enter JSON and parse it inside the snippet — it arrives as a string.
parseJsonOutputbooleanNotrueParse the complete standard output as JSON into result. The run can still succeed if parsing fails.
timeoutSecondsintegerNo5Wall-clock limit for the snippet, from 1 to 30 seconds.
maxOutputBytesintegerNo256000Combined stdout + stderr cap, maximum 1048576 (1 MB).
saveFilesstring arrayNo[]Up to 10 relative paths, written by the snippet, to preserve in the key-value store.
maxSavedFileBytesintegerNo5000000Combined size cap for saved files, maximum 10485760 (10 MB).

Output fields

Every run pushes exactly one record to the dataset.

FieldTypeDescription
statusstringsucceeded, failed, or timed_out.
languagestringRuntime selected by the input.
exitCodeinteger / nullNumeric subprocess exit code, or null after signal termination.
signalstring / nullTerminating signal name (e.g. SIGKILL) when the process was killed.
stdoutstringCaptured standard output (subject to maxOutputBytes).
stderrstringCaptured standard error and spawn diagnostics.
durationMsintegerWall-clock execution duration in milliseconds.
timedOutbooleanWhether the wall timer stopped execution.
outputTruncatedbooleanWhether the combined output cap was reached.
terminationReasonstring / nulltimeout, output_limit, or spawn_error when applicable.
resultJSON value / nullValue parsed from stdout when parseJsonOutput is enabled.
resultParseErrorstring / nullParsing error when stdout is not valid JSON.
filesarraySaved-file references: path, key, bytes, and a url — or path and error.
executedAtstringISO 8601 timestamp of the terminal record.

User-code failures still produce a record. Check status and exitCode before trusting result. If JSON parsing fails the execution can still be succeeded — read stdout and resultParseError to decide whether the data contract was met.

Output example

{
"status": "succeeded",
"language": "javascript",
"exitCode": 0,
"signal": null,
"stdout": "{\"sum\":16,\"count\":3}\n",
"stderr": "",
"durationMs": 48,
"timedOut": false,
"outputTruncated": false,
"terminationReason": null,
"result": { "sum": 16, "count": 3 },
"resultParseError": null,
"files": [],
"executedAt": "2026-07-24T12:00:00.000Z"
}

A run that writes a file:

{
"status": "succeeded",
"language": "python",
"exitCode": 0,
"signal": null,
"stdout": "{\"rows\":128}\n",
"stderr": "",
"durationMs": 213,
"timedOut": false,
"outputTruncated": false,
"terminationReason": null,
"result": { "rows": 128 },
"resultParseError": null,
"files": [
{ "path": "export.csv", "key": "file-0-export.csv", "bytes": 40213, "url": "https://api.apify.com/v2/key-value-stores/.../records/file-0-export.csv" }
],
"executedAt": "2026-07-24T12:00:00.000Z"
}

How to run code in the sandbox

  1. Open the Actor and go to the Input tab.
  2. Choose the Languagejavascript or python.
  3. Paste your Code. Read input from standard input and print your result — ideally a single JSON value — to standard output. Send diagnostics to standard error.
  4. Set Standard input to the data your snippet needs — enter JSON like { "values": [3, 5, 8] } (parse it in your snippet) or any plain text.
  5. Leave Parse JSON output on to get a typed result, or turn it off if your snippet prints plain text or CSV.
  6. Adjust Timeout and Max output bytes if needed. Keep them small for the first run.
  7. Add relative paths to Save files only if your snippet generates files you need downstream.
  8. Click Start. When the run finishes, open the Dataset tab (or Storage → Key-value store for saved files) and read the execution record.

Prefer the API? See the examples below.

Run from the Apify API — Python

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run_input = {
"language": "python",
"code": (
"import sys, json\n"
"data = json.load(sys.stdin)\n"
"vals = data['values']\n"
"print(json.dumps({'sum': sum(vals), 'avg': sum(vals) / len(vals)}))"
),
"stdin": '{"values": [3, 5, 8]}',
"parseJsonOutput": True,
"timeoutSeconds": 5,
}
run = client.actor("parsebird/code-runner-sandbox").call(run_input=run_input)
for record in client.dataset(run["defaultDatasetId"]).iterate_items():
print(record["status"], record["result"])

Run from the Apify API — JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const input = {
language: 'javascript',
code: `
const chunks = [];
for await (const chunk of process.stdin) chunks.push(chunk);
const input = JSON.parse(Buffer.concat(chunks).toString() || '{}');
console.log(JSON.stringify({ sum: input.values.reduce((a, b) => a + b, 0) }));
`,
stdin: JSON.stringify({ values: [3, 5, 8] }),
parseJsonOutput: true,
timeoutSeconds: 5,
};
const run = await client.actor('parsebird/code-runner-sandbox').call(input);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0].status, items[0].result);

You can also call the Actor over plain HTTP with the Run Actor endpoint, or add it to an Apify MCP server so an AI assistant can run code on demand.

How it works

  1. Validate the request. Missing language/code, an invalid limit, oversized source, or an unavailable runtime fail the Actor run before anything executes.
  2. Stage the snippet. The code is written to a fresh temporary directory owned by the sandbox user.
  3. Spawn the child. The subprocess starts in a new session (its own process group), dropped to a dedicated unprivileged UID/GID with a minimal environment and CPU, file-descriptor, and process limits. JavaScript gets a V8 heap ceiling and Python gets an address-space ceiling, both derived from the run's memory — raise the run memory to give the snippet more room.
  4. Stream I/O. Standard input is fed to the process; standard output and standard error are captured concurrently and counted against the combined byte cap.
  5. Enforce bounds. When the wall timer expires or the output cap is hit, the whole process group is signalled and force-killed.
  6. Collect results. Requested files are validated (must stay inside the working directory, within the size cap) and uploaded to the key-value store. Standard output is optionally parsed as JSON.
  7. Emit the record. One dataset item is pushed, the temporary directory is deleted, and the run is charged once.

Security model and limitations

The child process runs under a dedicated UID/GID 10001, with no_new_privs, a minimal environment, and limited CPU time, file descriptors, and process count. It does not receive APIFY_TOKEN or any other parent environment variables. The temporary directory is deleted after the terminal record and requested files are stored. State never carries into another run.

However, this Actor is not a hardware VM and does not claim protection equivalent to a specialized microVM sandbox. Submitted code can use the runtime's networking APIs. Do not place passwords, API keys, private records, or untrusted third-party secrets in code or stdin. Use it for bounded transformations where you control or have reviewed the snippet.

Version 1 is a stateless process runner, not a persistent VM or interactive shell. It intentionally excludes package installation (npm install, pip install), arbitrary shell commands, coding-agent CLIs, and long-running services. Each run is independent and repeatable.

How much does it cost to run code in the sandbox?

Pricing is pay-per-event: one code-execution event per run, billed whether the snippet succeeded, failed, timed out, or hit the output cap — the bounded runtime and full diagnostics are always produced. Actor-contract failures (missing code, invalid limits, oversized source) fail the run and are not charged.

PlanPrice per runPrice per 1,000 runs
Free$0.00099$0.99
Bronze$0.00079$0.79
Silver$0.00049$0.49
Gold$0.00039$0.39

Running 1,000 transformations costs $0.99 on the Free plan and $0.39 on the Gold plan, plus the platform compute usage for the run itself. Apify's monthly platform credits on the Free plan cover a large number of runs. See Apify pricing for plan details.

Yes. Running your own code in a sandbox is a standard development and automation task. You are responsible for the snippets you submit and for complying with the terms of any service your code contacts over the network, as well as applicable data-protection laws (such as GDPR) when your code processes personal data. Do not use the Actor to execute code you have not reviewed, and do not pass secrets through code or stdin. For background, see the Apify blog on the legality of web scraping and automation.

  • HTTP Request — send a configurable HTTP request and capture the full response, headers, and timing.
  • PDF Text Extractor — extract embedded text and metadata from PDF files by URL.
  • Data Cleaner — normalize, deduplicate, and reshape dataset records with configurable rules.
  • Dataset Deduplicator — remove duplicate items from an Apify dataset by key.
  • RSS Feed Extractor — parse RSS and Atom feeds into structured items.

Browse all ParseBird actors for more automation building blocks.

FAQ

Which languages are supported? javascript runs on Node.js 22 and python runs on Python 3. Choose one per run with the language input. There is no TypeScript compiler, no browser runtime, and no other language in version 1.

Is JavaScript CommonJS or ESM? The snippet runs as an ES module: use import (not require), and top-level await is available. To load a built-in with the CommonJS style, use import { readFile } from 'node:fs/promises' or import { createRequire } from 'node:module'.

How do I pass data to my code? Use the stdin input. It is written to the snippet's standard input as-is. To pass structured data, enter JSON text and parse it in your snippet (JSON.parse / json.load). Keep your code deterministic and pass changing data through stdin so runs stay reproducible.

How do I get a typed result instead of a string? Print a single JSON value to standard output and leave parseJsonOutput on. The parsed value appears in result. If the output is not valid JSON, result stays null, resultParseError explains why, and the run can still be succeeded — so always check both.

What happens when my code times out? At timeoutSeconds the whole process group is signalled and then force-killed, including any child processes the snippet started. The record has status: "timed_out", timedOut: true, and terminationReason: "timeout".

What happens when my code prints too much? maxOutputBytes caps stdout and stderr combined. Once reached, execution stops, the already-captured bytes are kept, outputTruncated is set to true, and terminationReason is "output_limit".

Can I install npm or pip packages? Not in version 1. Only the runtime's standard library and built-in modules are available. Bundle any helper code directly into your snippet.

Can my code make network requests? Yes — the runtime's networking APIs are available. Because of that, never run code you have not reviewed and never pass credentials through code or stdin.

How large can my code and my files be? Source is capped at 100 KB. Saved files are capped by maxSavedFileBytes (up to 10 MB combined), and you can request at most 10 paths. Files must be written inside the working directory.

My snippet runs out of memory — what can I do? The run's memory allocation is the hard boundary for the snippet, and the JavaScript V8 heap and Python address-space limits are derived from it. The default run is 512 MB, which is enough for most transformations. For memory-heavy work (large pandas/numpy operations, big in-memory datasets), open the Input tab, expand Options, and raise Memory — up to 2 GB. A failed status with a MemoryError (Python) or an out-of-memory exit (JavaScript) is the signal to increase it.

Does anything persist between runs? No. The temporary directory is deleted after each run and no state carries over. Saved files live in that run's key-value store only.

Can I schedule runs or call this from the API? Yes. Use Apify Schedules for recurring runs and the Apify API or client libraries to run it programmatically. It also works as an MCP tool and in Zapier, Make, and n8n.

Something looks wrong — how do I report it? Open an issue on the Actor's Issues tab with your input and the execution record. Feedback and feature requests are welcome.