DEV Community

Om Prakash
Om Prakash

Posted on

Stop Paying $0.10/Image for Product Photography APIs — Here's a 2¢ Alternative

If you're building an e-commerce tool, a Shopify app, or a marketplace integration in India, you've probably looked at background removal and product photo APIs.

PhotoRoom charges $0.10/image. Remove.bg is $0.06–0.12/image at volume. For a seller with 1,000 SKUs, that's $60–100 just for background removal before you've done anything else.

We built PixelAPI — a self-hosted AI image API running on our own GPU cluster. Here's what the same workflow costs with us: $0.01/image (1 credit = $0.001, background removal = 10 credits).

Let me show you a real product photography pipeline in Python.

The Full Pipeline: Smartphone Photo → Marketplace-Ready Image

import requests
import base64

API_KEY = "your_pixelapi_key"
BASE = "https://api.pixelapi.dev/v1"
headers = {"Authorization": f"Bearer {API_KEY}"}

def product_photo_pipeline(image_path: str, output_path: str):
    """
    Full pipeline: remove bg → upscale → enhance
    Cost: ~60 credits ($0.06) vs $0.30+ with major providers
    """
    with open(image_path, "rb") as f:
        image_bytes = f.read()

    # Step 1: Remove background (10 credits)
    print("Step 1: Removing background...")
    r = requests.post(
        f"{BASE}/image/remove-background",
        headers=headers,
        files={"image": ("product.jpg", image_bytes, "image/jpeg")}
    )
    r.raise_for_status()
    gen_id = r.json()["generation_id"]

    # Poll for result
    import time
    for _ in range(30):
        result = requests.get(f"{BASE}/image/{gen_id}", headers=headers).json()
        if result["status"] == "completed":
            clean_image = requests.get(result["output_url"]).content
            break
        time.sleep(2)

    # Step 2: Upscale 4x for marketplace quality (50 credits)
    print("Step 2: Upscaling 4x...")
    r = requests.post(
        f"{BASE}/image/upscale",
        headers=headers,
        files={"image": ("clean.png", clean_image, "image/png")},
        data={"scale": 4}
    )
    r.raise_for_status()
    gen_id = r.json()["generation_id"]

    for _ in range(60):
        result = requests.get(f"{BASE}/image/{gen_id}", headers=headers).json()
        if result["status"] == "completed":
            final_image = requests.get(result["output_url"]).content
            break
        time.sleep(3)

    with open(output_path, "wb") as f:
        f.write(final_image)

    print(f"Done! Saved to {output_path}")
    print("Total cost: ~60 credits ($0.06)")

product_photo_pipeline("iphone_photo.jpg", "marketplace_ready.png")
Enter fullscreen mode Exit fullscreen mode

What This Actually Does

The pipeline handles the two biggest rejection causes on Amazon India and Flipkart:

  1. Cluttered backgrounds — BiRefNet removes them precisely, even hair and transparent objects
  2. Low resolution — Real-ESRGAN upscales 4x without the blurry interpolation artifacts you get from Photoshop

You get a clean PNG on white, at 4x the original resolution. Ready for any marketplace.

Adding White Background (Marketplace Compliance)

Amazon India requires 1000×1000px minimum, pure white (RGB 255,255,255) background. Add this post-processing step:

from PIL import Image
import io

def add_white_background(png_bytes: bytes, size: tuple = (1000, 1000)) -> bytes:
    """Add white background and resize for Amazon/Flipkart compliance"""
    img = Image.open(io.BytesIO(png_bytes)).convert("RGBA")

    # Create white canvas
    background = Image.new("RGBA", size, (255, 255, 255, 255))

    # Fit product maintaining aspect ratio
    img.thumbnail(size, Image.LANCZOS)
    offset = ((size[0] - img.width) // 2, (size[1] - img.height) // 2)
    background.paste(img, offset, img)

    # Convert to RGB (JPEG doesn't support alpha)
    result = background.convert("RGB")
    buf = io.BytesIO()
    result.save(buf, format="JPEG", quality=95)
    return buf.getvalue()
Enter fullscreen mode Exit fullscreen mode

Batch Processing 1,000 SKUs

import concurrent.futures
import csv

def process_catalog(csv_path: str, output_dir: str):
    """Process a product catalog CSV concurrently"""
    with open(csv_path) as f:
        products = list(csv.DictReader(f))

    def process_one(product):
        try:
            product_photo_pipeline(
                product["image_path"],
                f"{output_dir}/{product['sku']}.jpg"
            )
            return product["sku"], "ok"
        except Exception as e:
            return product["sku"], str(e)

    with concurrent.futures.ThreadPoolExecutor(max_workers=5) as ex:
        results = list(ex.map(process_one, products))

    ok = sum(1 for _, s in results if s == "ok")
    print(f"Done: {ok}/{len(products)} successful")

# 1,000 products at $0.06 each = $60 total
# Same pipeline with PhotoRoom API: $100+
process_catalog("catalog.csv", "./output")
Enter fullscreen mode Exit fullscreen mode

Cost Comparison (1,000 Products)

Step PhotoRoom Remove.bg PixelAPI
Background removal $100 $60–120 $10
4x Upscaling Not available Not available $50
Face restore Not available Not available $25
Total for 1,000 SKUs $100 $60–120 $60

And with PixelAPI you get all three operations for $60. PhotoRoom's equivalent (just background removal) alone costs $100.

New: Image-to-Video for Product Demos

We just shipped Image-to-Video using WAN 2.1 — you can animate a product photo into a 3–5 second showcase clip. 20 credits for 480p, 35 for 720p.

# Turn a product image into a demo video
r = requests.post(
    f"{BASE}/video/i2v",
    headers=headers,
    files={"image": ("product.jpg", open("product.jpg", "rb"), "image/jpeg")},
    data={
        "prompt": "Product rotating slowly on white background, studio lighting, 360 view",
        "resolution": "480p",
        "duration": 3.0
    }
)
print(r.json())  # {"generation_id": "...", "status": "queued", "credits_used": 20}
Enter fullscreen mode Exit fullscreen mode

Webhook Integration (No More Polling)

For production systems, use webhooks instead of polling:

# Set webhook once
requests.put(
    f"{BASE}/account/webhook",
    headers=headers,
    json={"webhook_url": "https://yourapp.com/pixelapi-callback", "regenerate_secret": True}
)

# Your FastAPI handler
from fastapi import FastAPI, Request
import hmac, hashlib

app = FastAPI()

@app.post("/pixelapi-callback")
async def handle_result(request: Request):
    body = await request.body()
    sig = request.headers.get("X-PixelAPI-Signature", "")

    # Verify signature
    expected = "sha256=" + hmac.new(
        YOUR_WEBHOOK_SECRET.encode(),
        body,
        hashlib.sha256
    ).hexdigest()

    if not hmac.compare_digest(sig, expected):
        return {"error": "invalid signature"}

    payload = await request.json()
    if payload["status"] == "completed":
        # Process completed job
        download_and_store(payload["generation_id"], payload["output_url"])

    return {"ok": True}
Enter fullscreen mode Exit fullscreen mode

Free tier: 100 credits/month, no credit card.

Paid from $10/10,000 credits — enough for ~166 full product photo pipelines.

Get your API key at pixelapi.dev

The Python SDK is on the roadmap — for now the REST API is straightforward enough that you don't need one.

Built on self-hosted RTX 4070 + RTX 6000 Ada GPUs. Zero cloud GPU costs = prices that actually make sense for Indian developers.

Top comments (1)

Collapse
 
harjjotsinghh profile image
Harjot Singh

Cost arbitrage on AI APIs is real and underexploited, the gap between the convenient API and the 2-cent alternative is mostly people not wanting to wire the cheaper path. The tradeoff to watch is reliability and quality variance, the cheap route is great until it's down or off-spec and you've got no fallback. The robust pattern is cheap-by-default with automatic escalation to the pricier API when a quality check fails. That cost-routing-with-a-safety-net is exactly how I keep Moonshift runs cheap without shipping garbage. Are you running any quality check on the 2-cent output, or trusting it outright?