Piston API alternative
The public Piston API is closed. Here's a hosted replacement.
Since 15 February 2026, emkc.org only runs code for whitelisted, non-commercial educational projects. If your app called it, it now gets a 401. Here are your options, and how to move your Piston calls to OnlineCompiler.io by changing the base URL.
By the OnlineCompiler.io team. Updated . We make OnlineCompiler.io, so we're one of the options here. Every competitor figure links to the vendor's own page, and we say where our API falls short.
What changed
The Piston README now says the public API is no longer freely
available, and that authorization is only granted to good-cause, non-commercial educational projects.
Requests to https://emkc.org/api/v2/piston/execute without a whitelisted key get HTTP 401 and the message "Public Piston API is now whitelist only as of 2/15/2026".
Before this, the public API allowed 5 requests a second with no key, which is why so many hobby projects, Discord bots, classroom tools and coding-practice sites were built on it.
Your three options
| Option | Good fit when | What it costs you |
|---|---|---|
| Apply for whitelisting | Your project is non-commercial and educational. | Asking on the EngineerMan Discord and waiting. Paid, individual, portfolio, coursework and AI-generated projects don't qualify. |
| Self-host Piston | You need one of its 84 languages, want full control, or already run servers. | Free software (MIT), but you run the Docker host, install packages, and handle updates, security and scaling. |
| Switch to a hosted API | You want to keep shipping without running sandboxes. | A new base URL and API key. OnlineCompiler.io is free up to 100,000 runs a month; see how the hosted options compare. |
Switch by changing the base URL
OnlineCompiler.io answers Piston's v2 API at https://api.onlinecompiler.io/api/v2/piston. Point your Piston
client or HTTP calls there and send your API key in the Authorization header. The /runtimes and /execute endpoints keep Piston's request and response shapes,
and errors come back as {"message": "..."}, so code that handled Piston's answers
keeps working. Keep the API key on your server; never ship it to the browser.
curl -X POST https://api.onlinecompiler.io/api/v2/piston/execute \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"language": "python",
"version": "3.10.0",
"files": [{ "name": "main.py", "content": "print(input()[::-1])" }],
"stdin": "piston"
}'| Piston (emkc.org) | OnlineCompiler.io |
|---|---|
https://emkc.org/api/v2/piston | https://api.onlinecompiler.io/api/v2/piston |
| Whitelisted key | Authorization: YOUR_API_KEY, free to create |
GET /runtimes | Same shape: our 12 languages under Piston's names and aliases (py, c++, csharp...) |
version | Accepted and ignored: the current version in the table below runs |
files, args | One file, in utf8, base64 or hex; no command-line arguments |
compile stage | None: compiler errors arrive in run.stderr with a non-zero run.code |
run.status | RE, TO, SG, OL and XX, as in Piston |
run.cpu_time | null; wall_time (ms) and memory (bytes) are filled in |
The full list of differences is in the API docs. Runs count toward your monthly allowance like any other request.
Or move to the native API
The native endpoints add async callbacks, WebSocket, the embeddable editor and MCP. The sync endpoint takes one source file and optional stdin, and returns the result in the same request, like Piston does.
| Piston request | OnlineCompiler.io |
|---|---|
language + version | compiler, one id per language, such as python-3.14 |
files[0].content | code |
stdin | input |
files[1..], args | Not supported: one file, no command-line arguments |
run_timeout, run_memory_limit and the other limits | Fixed per run: 30 s, 512 MB, 2 CPUs |
Authorization (whitelisted key) | Authorization: YOUR_API_KEY |
Mapping the response
| Piston response | OnlineCompiler.io |
|---|---|
run.stdout | output |
run.stderr | error |
run.output (both streams) | Not returned; join output and error |
run.code | exit_code |
run.signal | signal, as a number (9 for SIGKILL), or null |
compile stage | No separate object; compile errors arrive in error with status: "error" |
run.status TO (timeout) | exit_code 124 |
run.status OL / EL (output too long) | truncated: true, with the first 64 KB kept |
run.cpu_time, wall_time (ms) | time (run) and total (with compile), in seconds, as strings |
run.memory (bytes) | memory, in KB, as a string |
Language mapping
The versions on the public Piston instance are several years old. Each language on OnlineCompiler.io runs a current release:
| Piston language | Piston version (emkc.org) | compiler | Version |
|---|---|---|---|
python | 3.10.0 | python-3.14 | Python 3.14 |
c | GCC 10.2.0 | gcc-15 | C GCC 15 |
c++ | GCC 10.2.0 | g++-15 | C++ G++ 15 |
java | 15.0.2 | openjdk-25 | Java OpenJDK 25 |
csharp / csharp.net | Mono 6.12 / .NET 5.0 | dotnet-csharp-9 | C# .NET SDK 9 |
fsharp.net | .NET 5.0 | dotnet-fsharp-9 | F# .NET SDK 9 |
go | 1.16.2 | go-1.26 | Go 1.26 |
rust | 1.68.2 | rust-1.93 | Rust 1.93 |
php | 8.2.3 | php-8.5 | PHP 8.5 |
ruby | 3.0.1 | ruby-4.0 | Ruby 4.0 |
haskell | 9.0.1 | haskell-9.12 | Haskell GHC 9.12 |
typescript | 5.0.3 (Node) / Deno 1.32.3 | typescript-deno | TypeScript Deno |
Plain JavaScript runs under typescript-deno, since Deno runs TypeScript files without
type-checking. Node-only APIs such as require() may not work there. Read stdin with fs.readFileSync(0) or Deno.stdin; Deno refuses /dev/stdin.
What's different from Piston
- Fewer languages: 12, against Piston's 84.
- One file per run, with no command-line arguments.
- One version per language: the requested version is ignored, and there's no separate compile stage in the response.
- Fixed limits: 30 seconds, 512 MB and 2 CPUs per run. That's more time than Piston's 3-second default, but you can't raise it per request.
- More output: up to 64 KB per stream, against Piston's default of
1,024 characters, with
truncated: truewhen it had to cut. - Isolation: every run gets a fresh gVisor sandbox (a user-space kernel) with no network access.
- More ways in: besides the sync endpoint there's an async endpoint with callbacks, WebSocket, an embeddable editor and an MCP server.
Frequently asked questions
Is the public Piston API still free?
No. Since 15 February 2026 the public API at emkc.org only accepts requests from whitelisted projects, and whitelisting is granted only to non-commercial educational projects. Everyone else has to self-host Piston or use another service.
Why does emkc.org return 401 Unauthorized?
Requests without a whitelisted key get HTTP 401 with a message saying the public Piston API is now whitelist only as of 2/15/2026. Nothing is wrong with your request; the service closed to the public.
Can I self-host Piston instead?
Yes. Piston is MIT-licensed and runs in Docker. You run the servers, install the language packages you need, and handle updates, security and scaling yourself.
Do I have to rewrite my Piston calls?
No. Change the base URL from https://emkc.org/api/v2/piston to https://api.onlinecompiler.io/api/v2/piston and send your OnlineCompiler.io API key in the Authorization header. The runtimes and execute endpoints keep Piston's request and response shapes. Programs with more than one file or with command-line args are rejected with a message.
Is OnlineCompiler.io free for commercial projects?
Yes. The free plan includes 100,000 runs a month and allows commercial use, with no credit card.
Does OnlineCompiler.io support every Piston language?
No. It supports 12 languages, against Piston's 84. If you need a language outside that list, keep a self-hosted Piston for it and send the rest to OnlineCompiler.io.