Stability AI Free code examples in Python and JavaScript
Stable Diffusion image generation, upscaling and background removal.
WHAT THIS PAGE COVERS
Image-to-image, where the strength parameter decides everything.
sd3.5-large
requests
Model ids change. If a sample returns a 404 on the model, that is the first thing to check against the official docs.
No official Python SDK — Stability documents the REST API, and requests is enough. That is the more durable sample anyway.
pip install requests
export STABILITY_API_KEY="sk-your-key" # macOS / Linux
setx STABILITY_API_KEY "sk-your-key" # Windows, then open a new shell
files={'none': ''} IS LOAD-BEARING. Without it requests sends form-urlencoded and the API returns a validation error that says nothing about encoding. The accept header decides bytes versus base64.
import os
import requests
response = requests.post(
"https://api.stability.ai/v2beta/stable-image/generate/sd3",
headers={
"authorization": f"Bearer {os.environ['STABILITY_API_KEY']}",
"accept": "image/*", # application/json would give base64
},
files={"none": ""}, # forces multipart encoding
data={
"prompt": "A studio photograph of a brass microphone on a dark desk",
"model": "sd3.5-large",
"output_format": "png",
},
timeout=120,
)
response.raise_for_status()
with open("microphone.png", "wb") as handle:
handle.write(response.content)
STRENGTH IS THE WHOLE PARAMETER. Below about 0.3 the output is the input with a filter on it; above about 0.8 the input may as well not have been sent. The useful range is narrow and worth sweeping before tuning the prompt.
with open("sketch.png", "rb") as source:
response = requests.post(
"https://api.stability.ai/v2beta/stable-image/generate/sd3",
headers={
"authorization": f"Bearer {os.environ['STABILITY_API_KEY']}",
"accept": "image/*",
},
files={"image": source},
data={
"prompt": "A brass microphone, studio lighting, photographic",
"model": "sd3.5-large",
"mode": "image-to-image", # required when image is present
"strength": 0.55, # 0 keeps the input, 1 ignores it
"output_format": "png",
},
timeout=120,
)
response.raise_for_status()
open("rendered.png", "wb").write(response.content)
Five requests and a contact sheet answer the question faster than an afternoon of single tries. Fix the seed, or you are comparing strength AND noise at the same time.
for strength in (0.35, 0.45, 0.55, 0.65, 0.75):
with open("sketch.png", "rb") as source:
response = requests.post(
"https://api.stability.ai/v2beta/stable-image/generate/sd3",
headers={
"authorization": f"Bearer {os.environ['STABILITY_API_KEY']}",
"accept": "image/*",
},
files={"image": source},
data={
"prompt": "A brass microphone, studio lighting, photographic",
"model": "sd3.5-large",
"mode": "image-to-image",
"strength": strength,
"seed": 42, # hold it fixed or this proves nothing
"output_format": "png",
},
timeout=120,
)
response.raise_for_status()
open(f"strength-{strength}.png", "wb").write(response.content)
A different route on the same API and the cheapest thing here. No prompt at all — it is a segmentation model, so the only useful knob is the output format.
with open("product.png", "rb") as source:
response = requests.post(
"https://api.stability.ai/v2beta/stable-image/edit/remove-background",
headers={
"authorization": f"Bearer {os.environ['STABILITY_API_KEY']}",
"accept": "image/*",
},
files={"image": source},
data={"output_format": "png"}, # png keeps the alpha channel
timeout=120,
)
response.raise_for_status()
open("cutout.png", "wb").write(response.content)
Nothing to install on modern Node — fetch, FormData and Blob are all built in. Server-side only.
# Node 18+ has fetch, FormData and Blob built in.
export STABILITY_API_KEY="sk-your-key"
DO NOT SET Content-Type. fetch computes the multipart boundary from the FormData, and setting the header by hand omits it — the request then fails with an error about a missing prompt, which is a lie.
import { writeFile } from "node:fs/promises";
const form = new FormData();
form.set("prompt", "A studio photograph of a brass microphone on a dark desk");
form.set("model", "sd3.5-large");
form.set("output_format", "png");
const response = await fetch(
"https://api.stability.ai/v2beta/stable-image/generate/sd3",
{
method: "POST",
headers: {
authorization: `Bearer ${process.env.STABILITY_API_KEY}`,
accept: "image/*",
// No content-type — fetch sets it, with the boundary.
},
body: form,
},
);
if (!response.ok) throw new Error(await response.text());
await writeFile("microphone.png", Buffer.from(await response.arrayBuffer()));
STRENGTH IS THE WHOLE PARAMETER, and mode must be set the moment an image is attached. Leaving mode out with a file present is a 400 that names neither.
import { readFile } from "node:fs/promises";
const sketch = await readFile("sketch.png");
const form = new FormData();
form.set("image", new Blob([sketch], { type: "image/png" }), "sketch.png");
form.set("prompt", "A brass microphone, studio lighting, photographic");
form.set("model", "sd3.5-large");
form.set("mode", "image-to-image"); // required once image is present
form.set("strength", "0.55"); // 0 keeps the input, 1 ignores it
form.set("output_format", "png");
const response = await fetch(
"https://api.stability.ai/v2beta/stable-image/generate/sd3",
{
method: "POST",
headers: {
authorization: `Bearer ${process.env.STABILITY_API_KEY}`,
accept: "image/*",
},
body: form,
},
);
if (!response.ok) throw new Error(await response.text());
await writeFile("rendered.png", Buffer.from(await response.arrayBuffer()));
Sequential, not Promise.all: Stability rate-limits and a 429 costs a 60-second timeout, which is slower than just doing them in order.
const sketch = await readFile("sketch.png");
for (const strength of [0.35, 0.45, 0.55, 0.65, 0.75]) {
const form = new FormData();
form.set("image", new Blob([sketch], { type: "image/png" }), "sketch.png");
form.set("prompt", "A brass microphone, studio lighting, photographic");
form.set("model", "sd3.5-large");
form.set("mode", "image-to-image");
form.set("strength", String(strength));
form.set("seed", "42"); // hold it fixed or this proves nothing
form.set("output_format", "png");
const response = await fetch(
"https://api.stability.ai/v2beta/stable-image/generate/sd3",
{
method: "POST",
headers: {
authorization: `Bearer ${process.env.STABILITY_API_KEY}`,
accept: "image/*",
},
body: form,
},
);
if (!response.ok) throw new Error(await response.text());
await writeFile(`strength-${strength}.png`,
Buffer.from(await response.arrayBuffer()));
}
With accept: image/* a success is bytes and a failure is JSON. Calling .arrayBuffer() on the failure gives you an unreadable buffer instead of the message, so branch on response.ok first.
async function generate(form) {
const response = await fetch(
"https://api.stability.ai/v2beta/stable-image/generate/sd3",
{
method: "POST",
headers: {
authorization: `Bearer ${process.env.STABILITY_API_KEY}`,
accept: "image/*",
},
body: form,
},
);
if (response.ok) return Buffer.from(await response.arrayBuffer());
// Errors come back as JSON whatever the accept header says.
const detail = await response.json().catch(() => ({}));
// 403 is content moderation, not auth — retrying will not help.
// 429 is rate limiting and carries a 60-second cool-off.
throw new Error(`Stability ${response.status}: ${JSON.stringify(detail)}`);
}
QUESTIONS
Which languages are the Stability AI examples in?
Python and JavaScript. Every sample runs as pasted and reads its credentials from an environment variable — no key is ever written into the code.
Which package do I install for Stability AI?
The samples use requests. The install step on each language tab gives the exact command.
Which Stability AI model do these examples use?
sd3.5-large, checked against the official documentation on 26 September 2026. Model ids change often; if a call returns a model-not-found error, check the current list in the official docs.
Where is the official Stability AI documentation?
https://platform.stability.ai/docs/api-reference — it is linked at the bottom of this page, and it is the authority whenever it disagrees with a sample here.
ALSO IN IMAGE & VIDEO
The authority
Official Stability AI documentation
Model names, pricing and rate limits change faster than any page here can. When this page and the official docs disagree, the official docs are right.
https://platform.stability.ai/docs/api-reference