Changing a photo's background to white, a brand color, or a gradient is one of the most common image edits. Doing it by hand means masking the subject in an editor. With an API it is one request: the subject is detected, the old background is removed, and the new color is applied.
Solid color backgrounds
Send the image to /v2/rembg/color/ with a bgcolor value in RGBA format: (red, green, blue, alpha), each from 0 to 255.
curl -X POST https://fapihub.com/v2/rembg/color/ \
-H "ApiKey: YOUR_API_KEY" \
-F "image=@headshot.jpg" \
-F "bgcolor=(255, 140, 0, 255)" \
--output headshot-orange.pngConverting a hex color to RGBA
Brand guidelines usually list hex codes. This helper converts them:
def hex_to_rgba(hex_color: str, alpha: int = 255) -> str:
hex_color = hex_color.lstrip("#")
r, g, b = (int(hex_color[i:i + 2], 16) for i in (0, 2, 4))
return f"({r}, {g}, {b}, {alpha})"
hex_to_rgba("#1E40AF") # "(30, 64, 175, 255)"
Gradient backgrounds
For a more polished look, use /v2/rembg/gradient/ with a top_color and bottom_color. The background fades vertically from one to the other.
import requests
with open("headshot.jpg", "rb") as image_file:
response = requests.post(
"https://fapihub.com/v2/rembg/gradient/",
headers={"ApiKey": "YOUR_API_KEY"},
files={"image": image_file},
data={
"top_color": "(255, 140, 0, 255)",
"bottom_color": "(255, 220, 160, 255)",
},
timeout=60,
)
response.raise_for_status()
with open("headshot-gradient.png", "wb") as out:
out.write(response.content)
Getting the color format right
The bgcolor, top_color, and bottom_color values are strings that look like Python tuples: four integers from 0 to 255, separated by commas, inside parentheses. A typo such as a missing value or a number above 255 returns a 400 invalid_image error, and that failed request still counts against your quota. Validating before you send saves both time and credits.
import re
RGBA_PATTERN = re.compile(r"^\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$")
def validate_rgba(value: str) -> str:
match = RGBA_PATTERN.match(value)
if not match or any(int(part) > 255 for part in match.groups()):
raise ValueError(f"Not a valid RGBA tuple string: {value!r}")
return value
validate_rgba("(30, 64, 175, 255)") # ok
validate_rgba("(30, 64, 175)") # raises ValueError
For normal backgrounds, keep alpha at 255. The fourth value is opacity, so anything lower makes the background partly see-through, which is rarely what a color change is meant to do. Preview any non-opaque value in the playground before using it in production.
Changing the background color in Node.js
The same request with Node 18+ and built-in fetch. This version accepts a hex code so it fits naturally into a front end or CMS that stores brand colors that way.
import { readFile, writeFile } from "node:fs/promises";
function hexToRgba(hex, alpha = 255) {
const clean = hex.replace("#", "");
const [r, g, b] = [0, 2, 4].map((i) => parseInt(clean.slice(i, i + 2), 16));
return `(${r}, ${g}, ${b}, ${alpha})`;
}
async function changeBackground(inputPath, outputPath, hex) {
const form = new FormData();
form.append("image", new Blob([await readFile(inputPath)]), "photo.jpg");
form.append("bgcolor", hexToRgba(hex));
const response = await fetch("https://fapihub.com/v2/rembg/color/", {
method: "POST",
headers: { ApiKey: process.env.FAPIHUB_API_KEY },
body: form,
});
if (!response.ok) {
const { error } = await response.json();
throw new Error(`${response.status} ${error.code}: ${error.message}`);
}
await writeFile(outputPath, Buffer.from(await response.arrayBuffer()));
}
await changeBackground("headshot.jpg", "headshot-blue.png", "#1E40AF");
Popular uses
- Team pages: give every employee headshot the same brand-colored background, no matter where it was taken.
- ID and badge photos: standardize to a plain light background. Check the specific rules for official documents, which often require a particular shade.
- Social media and ads: place products on bold campaign colors or gradients.
- Marketplaces: use
(255, 255, 255, 255)for pure white main images.
Color picks that work
- Light, slightly warm neutrals (like
(248, 246, 242, 255)) flatter skin tones and most products. - Gradients look best when the two colors are close in hue. Try one color and a lighter version of it.
- Avoid a background close to the subject's main color. A red product on a red background loses its edges.
One cutout, many colors
If you need the same image in several colors, call /v2/rembg/ once to get a transparent PNG, then composite it onto each color with Pillow or Sharp. That uses one request instead of one per variant. Our transparent vs white background guide explains when to keep the transparent master. Try both endpoints in the playground first.
Building color variants locally
The section above recommends one cutout and local compositing when you need many colors. Here is what that looks like with Pillow, including a vertical gradient so you can match what the gradient endpoint produces without extra calls.
from PIL import Image
cutout = Image.open("headshot-transparent.png").convert("RGBA") # from /v2/rembg/
width, height = cutout.size
def on_color(rgb):
canvas = Image.new("RGBA", cutout.size, rgb + (255,))
return Image.alpha_composite(canvas, cutout).convert("RGB")
def on_gradient(top, bottom):
canvas = Image.new("RGBA", cutout.size)
for y in range(height):
t = y / max(1, height - 1)
row = tuple(round(a + (b - a) * t) for a, b in zip(top, bottom)) + (255,)
canvas.paste(row, (0, y, width, y + 1))
return Image.alpha_composite(canvas, cutout).convert("RGB")
brand_colors = {"white": (255, 255, 255), "navy": (30, 64, 175), "sand": (248, 246, 242)}
for name, rgb in brand_colors.items():
on_color(rgb).save(f"headshot-{name}.jpg", quality=92)
on_gradient((255, 140, 0), (255, 220, 160)).save("headshot-gradient.jpg", quality=92)
In Node.js, Sharp does the solid-color version in one line: sharp("headshot-transparent.png").flatten({ background: "#1E40AF" }).jpeg().toFile("headshot-navy.jpg"). More examples are in the Python background removal guide.
Endpoint per variant or local compositing?
| Color or gradient endpoint | One cutout + local compositing | |
|---|---|---|
| Requests per image | One per color | One total |
| Code to maintain | Just the API call | API call plus a compositing step |
| Best when | You need one fixed color per image | You need several colors, or colors that change later |
A worked example: a team page with 60 headshots in four brand colors. Calling the color endpoint for each variant is 240 requests, which is beyond the free Basic plan's 100 per month. Removing the background once per photo is 60 requests, which fits in the free plan, and you can add a fifth color next year without calling the API again. At larger volumes the same logic applies: the Pro plan's 7,500 monthly requests for $15 covers 7,500 single-color images, or many times that number of variants if you composite locally.
Choosing the output format
A solid or gradient background is fully opaque, so you do not need PNG's transparency for the final file. Convert to JPEG or WebP for web delivery to save space; the gradient code above already saves JPEG. Keep the transparent cutout as your master so you can regenerate any color later. If you see banding in a gradient after compression, raise the quality setting or use WebP. Our transparent vs white guide covers format choices for product catalogs in more depth.
Quality checklist before you ship
- View results on the target color at 100% zoom and check hair, fur, and fine edges for leftover pixels from the old background.
- Compare a light and a dark brand color. Edge fringing that is invisible on white can show up on navy.
- Confirm the exact RGB value with a color picker if a brand or document spec requires a precise shade.
- Check that a 400, 402, or 429 response stops or pauses your job instead of writing an error body to an image file.
Frequently asked questions
What format does bgcolor use?
An RGBA tuple string, for example (255, 255, 255, 255). Each value is an integer from 0 to 255; the last one is opacity. Hex codes are not accepted directly, so convert them first with a helper like the ones above.
Can I make a horizontal or diagonal gradient?
The gradient endpoint produces a vertical gradient from top_color to bottom_color. For other directions, get a transparent cutout from /v2/rembg/ and draw the gradient yourself with Pillow or Sharp.
Do the color and gradient endpoints cost more than background removal?
No. They are included on every plan and each call is one request, the same as a standard removal.
Can I choose the segmentation model for color changes?
The model parameter only applies to the standard removal and mask endpoints. If you want to compare models, request cutouts from /v2/rembg/ with each model and composite the color locally.