JavaScript + PixelPanda API

Remove Background with JavaScript

Remove image backgrounds with fetch() in the browser or Node.js. No canvas hacks, no WebAssembly. Just an HTTP call.

$ npm install form-data # Node.js only — browser needs no install

JavaScript examples — copy and go

Each example is self-contained. Copy the one that matches your use case.

Browser — quick start

Use the Fetch API with a file input. No npm packages needed.

const API_KEY = "pk_live_your_api_key";

async function removeBackground(file) {
    const form = new FormData();
    form.append("file", file);

    const response = await fetch(
        "https://pixelpanda.ai/api/v1/remove-background",
        {
            method: "POST",
            headers: { "Authorization": `Bearer ${API_KEY}` },
            body: form
        }
    );

    return await response.json();
}

// Hook up a file input
document.querySelector('input[type="file"]').addEventListener("change", async (e) => {
    const result = await removeBackground(e.target.files[0]);
    document.querySelector("img").src = result.image_url;
    console.log(`Credits remaining: ${result.credits_remaining}`);
});

Node.js — file upload

Process images from disk using Node.js and the form-data package.

const fs = require("fs");
const FormData = require("form-data");

const API_KEY = "pk_live_your_api_key";

async function removeBackground(imagePath) {
    const form = new FormData();
    form.append("file", fs.createReadStream(imagePath));

    const response = await fetch(
        "https://pixelpanda.ai/api/v1/remove-background",
        {
            method: "POST",
            headers: {
                "Authorization": `Bearer ${API_KEY}`,
                ...form.getHeaders()
            },
            body: form
        }
    );

    return await response.json();
}

// Process a single image
const result = await removeBackground("product.jpg");
console.log(result.image_url);

// Download the result
const img = await fetch(result.image_url);
const buffer = Buffer.from(await img.arrayBuffer());
fs.writeFileSync("product_nobg.png", buffer);

Process a folder of images

Loop through a directory and remove backgrounds from all images.

const fs = require("fs");
const path = require("path");
const FormData = require("form-data");

const API_KEY = "pk_live_your_api_key";
const INPUT_DIR = "./products";
const OUTPUT_DIR = "./products_nobg";

if (!fs.existsSync(OUTPUT_DIR)) fs.mkdirSync(OUTPUT_DIR);

const files = fs.readdirSync(INPUT_DIR)
    .filter(f => /\.(jpg|jpeg|png|webp)$/i.test(f));

console.log(`Processing ${files.length} images...`);

for (const [i, file] of files.entries()) {
    const form = new FormData();
    form.append("file", fs.createReadStream(path.join(INPUT_DIR, file)));

    try {
        const resp = await fetch("https://pixelpanda.ai/api/v1/remove-background", {
            method: "POST",
            headers: { "Authorization": `Bearer ${API_KEY}`, ...form.getHeaders() },
            body: form
        });

        const data = await resp.json();

        if (data.success) {
            const img = await fetch(data.image_url);
            const buffer = Buffer.from(await img.arrayBuffer());
            const outPath = path.join(OUTPUT_DIR, file.replace(/\.\w+$/, ".png"));
            fs.writeFileSync(outPath, buffer);
            console.log(`[${i + 1}/${files.length}] ${file} -> ${outPath}`);
        } else {
            console.log(`[${i + 1}/${files.length}] ${file} FAILED`);
        }
    } catch (err) {
        console.error(`[${i + 1}/${files.length}] ${file} ERROR: ${err.message}`);
    }

    await new Promise(r => setTimeout(r, 500)); // Rate limit delay
}

Error handling

Production-ready wrapper with retry logic.

async function removeBackgroundSafe(file, retries = 3) {
    for (let attempt = 1; attempt <= retries; attempt++) {
        try {
            const form = new FormData();
            form.append("file", file);

            const response = await fetch(
                "https://pixelpanda.ai/api/v1/remove-background",
                {
                    method: "POST",
                    headers: { "Authorization": `Bearer ${API_KEY}` },
                    body: form
                }
            );

            if (response.ok) return await response.json();

            if (response.status === 401) throw new Error("Invalid API key");
            if (response.status === 402) throw new Error("Out of credits");
            if (response.status === 429 && attempt < retries) {
                await new Promise(r => setTimeout(r, 2000 * attempt));
                continue; // Retry after backoff
            }

            throw new Error(`API error ${response.status}`);
        } catch (err) {
            if (attempt === retries) throw err;
        }
    }
}

React component

Drop-in React component with upload and preview.

import { useState } from "react";

function BackgroundRemover() {
    const [result, setResult] = useState(null);
    const [loading, setLoading] = useState(false);

    async function handleUpload(e) {
        const file = e.target.files[0];
        if (!file) return;

        setLoading(true);
        const form = new FormData();
        form.append("file", file);

        try {
            const resp = await fetch("/api/remove-bg", {  // Proxy through your backend
                method: "POST",
                body: form
            });
            const data = await resp.json();
            setResult(data.image_url);
        } catch (err) {
            console.error(err);
        } finally {
            setLoading(false);
        }
    }

    return (
        <div>
            <input type="file" accept="image/*" onChange={handleUpload} />
            {loading && <p>Removing background...</p>}
            {result && <img src={result} alt="Background removed" />}
        </div>
    );
}

Next.js API route

Server-side API route to keep your API key secret.

// app/api/remove-bg/route.js (Next.js App Router)
import { NextResponse } from "next/server";

export async function POST(request) {
    const formData = await request.formData();
    const file = formData.get("file");

    if (!file) {
        return NextResponse.json({ error: "No file" }, { status: 400 });
    }

    const apiForm = new FormData();
    apiForm.append("file", file);

    const response = await fetch(
        "https://pixelpanda.ai/api/v1/remove-background",
        {
            method: "POST",
            headers: {
                "Authorization": `Bearer ${process.env.PIXELPANDA_API_KEY}`
            },
            body: apiForm
        }
    );

    const data = await response.json();
    return NextResponse.json(data);
}

Response format

Every successful request returns this JSON. The image_url is a permanent link to the transparent PNG.

{
    "success": true,
    "image_url": "https://pub-xxx.r2.dev/results/abc123.png",
    "credits_remaining": 199
}
FieldTypeDescription
successbooleantrue if background was removed successfully
image_urlstringURL to the transparent PNG result (permanent, hosted on CDN)
credits_remainingintegerHow many credits are left on your account

Error codes

CodeMeaning
200Success — image_url contains the transparent PNG
400Bad request — invalid image format or missing file
401Unauthorized — invalid or missing API key
402Payment required — out of credits
413Image too large — max 10MB
429Rate limited — too many requests
500Server error — retry the request

Common issues

CORS error in browser
The API supports CORS, but for production use, proxy the request through your own backend (see Next.js example). This also keeps your API key secret.
Getting 401 Unauthorized
Check your API key is correct and included as 'Bearer pk_live_xxx' in the Authorization header. Keys start with pk_live_.
FormData not sending file correctly
Make sure you're appending the actual File object (from input.files[0]) or a ReadStream (Node.js), not a string path. Don't set Content-Type manually — let the browser/form-data set the multipart boundary.
Request times out
Large images take 3-5 seconds. Set your fetch timeout to at least 30 seconds. In Node.js, use AbortController with a timeout signal.

Common questions

Yes. Use the Fetch API with FormData — no npm packages needed in the browser. See the 'Browser — quick start' example above. Just keep your API key server-side in production (use a backend proxy).
See the React component and Next.js API route examples above. Accept a file upload in your component, send it to your backend API route, which forwards to PixelPanda and returns the result.
No SDK needed. In the browser, use the built-in fetch() and FormData. In Node.js, install the form-data package for multipart uploads. That's the only dependency.
Yes. Build your Shopify app with Node.js/Express or Remix, call the PixelPanda API from your backend, and update product images via the Shopify Admin API.
For development, the API supports CORS. For production, always proxy through your own backend to keep your API key secret. See the Next.js API route example.
Works great. The API returns: { success: boolean, image_url: string, credits_remaining: number }. Define an interface for type safety.
1 credit per image ($0.029). Start with 280 credits/week for $7.99 — no subscription. Monthly plans from $24/month for higher volume.

Start removing backgrounds with JavaScript

280 credits/week for $7.99. Copy the code above and go.

Get Your API Key