Piston API error
Piston API 401: "Public Piston API is now whitelist only as of 2/15/2026"
If POST https://emkc.org/api/v2/piston/execute now answers 401, nothing is wrong with your code. The public Piston API closed to everyone except approved projects on 15 February 2026. Here is the exact response, what it means, and how to get your app running again.
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.
The error
Calls to /execute on the public instance get HTTP 401 and a JSON body with a message. The wording has changed once; both versions are in the wild
(liveCodeShare#208, talent-IQ#19):
{
"message": "Public Piston API is now whitelist only as of 2/15/2026. Please host your own instance or go here and read the \"Important Note\" to see if you qualify for whitelisting: https://github.com/engineer-man/piston#public-api"
}HTTP error! status: 401
{"message":"Public Piston API is now whitelist only as of 2/15/2026. Please contact EngineerMan on Discord with use case justification or consider hosting your own Piston instance."}GET /runtimes kept answering for a while after the change, so a language list can load while every run fails.
Why it happens
The Piston README says the public API is no longer freely available and that authorization is only granted for good-cause, non-commercial educational projects, which you request on the EngineerMan Discord. Piston is open source (MIT); only the free hosted instance at emkc.org closed. A different language, version or request body will not change the answer.
Three ways out
- Ask to be whitelisted, if your project is non-commercial and educational. Expect to wait, and expect a no for portfolio and commercial work.
- Self-host Piston. It runs in Docker, and it is a fair choice if you need one of its 84 languages, want full control or already run servers. You then own the host, the language packages, updates, security and scaling.
- Use a hosted Piston-compatible API, covered below. It keeps your request and response shapes and costs a base URL, a key and a server-side call.
The fix with OnlineCompiler.io
OnlineCompiler.io answers Piston's v2 /runtimes and /execute at https://api.onlinecompiler.io/api/v2/piston, so the change is the URL and one header. Create a key on the API keys page (free, no card) and send it as the bare value of Authorization:
// Before: the public Piston API, called from the browser or your server
const res = await fetch("https://emkc.org/api/v2/piston/execute", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
language: "python",
version: "3.10.0",
files: [{ name: "main.py", content: "print(input()[::-1])" }],
stdin: "piston",
}),
});
// 401 { message: "Public Piston API is now whitelist only as of 2/15/2026..." }// After: the same body, a new URL and your key (server side only)
const res = await fetch("https://api.onlinecompiler.io/api/v2/piston/execute", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: process.env.ONLINECOMPILER_API_KEY, // the bare key, no "Bearer"
},
body: JSON.stringify({
language: "python",
version: "*", // accepted and ignored
files: [{ name: "main.py", content: "print(input()[::-1])" }],
stdin: "piston",
}),
});
const { run } = await res.json();
console.log(run.stdout); // "notsip\n"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":"*","files":[{"name":"main.py","content":"print(1 + 1)"}]}'Your files, stdin, language and the run.stdout, run.stderr, run.code response fields stay as they are. Piston language names and aliases
work for our 46 languages. version is accepted and ignored: the run uses the current
version /runtimes lists. Errors come back as {"message": "..."}, as on Piston.
Call it from your server, not the browser
The API sends no CORS headers, so a fetch from a web page is blocked, and a key in browser code is
public anyway. If your front end called emkc.org directly, add one small route on your own server and point the
front end at it:
// app/api/run/route.ts (Next.js). Your browser code calls /api/run, never us.
export async function POST(req: Request) {
const body = await req.json();
const res = await fetch("https://api.onlinecompiler.io/api/v2/piston/execute", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: process.env.ONLINECOMPILER_API_KEY!,
},
body: JSON.stringify(body),
});
return new Response(res.body, { status: res.status, headers: { "Content-Type": "application/json" } });
}To run code in the page itself with no server of your own, use the embeddable editor instead; its widget key is safe in public HTML.
What is different from Piston
- 46 languages, against Piston's 84. If you need one we lack, keep a self-hosted Piston for it.
- One source file per run, and no command-line
args. Extrafilesentries are input data the program reads. - Every run gets 512 MB and a 30-second limit, with no network access.
- No separate
compilestage: compiler errors arrive inrun.stderrwith a non-zerorun.code.
The full list is in the Piston-compatible API docs and the language table in Piston API alternatives.
Frequently asked questions
Why does the Piston API return 401 "whitelist only"?
Since 15 February 2026 the public Piston API at emkc.org only runs code for whitelisted projects. Every other POST /execute gets HTTP 401 with the message "Public Piston API is now whitelist only as of 2/15/2026". Your request is fine; the public service closed.
Is there an API key I can add to make it work again?
Only if EngineerMan whitelists you. The Piston README says authorization is granted only to good-cause, non-commercial educational projects, and you ask on the EngineerMan Discord. Portfolio, commercial and personal projects are not what it describes.
Do GET /runtimes calls still work?
Reports from May 2026 say GET /runtimes still answered while POST /execute was refused, so a language list loading is not proof that execution works.
Can I call OnlineCompiler.io from the browser instead?
No. The API sends no CORS headers, so a browser fetch is blocked, and an API key in browser code is public. Call it from your server and have the browser call your server.
What does it cost?
The free plan includes 100,000 runs a month (30 a minute) with no credit card, commercial use included.