← API reference

API guide · Node.js

Remove background from images in Node.js with the LassoCut API

Node.js 18 and later have fetch, FormData and Blob built in, so removing a background needs no package at all. This guide starts with one tested call, then runs a whole folder through a small promise pool of three concurrent requests with retries, and explains what to change in an existing axios or undici setup.

Quickstart

Every request needs your key in the X-Api-Key header and exactly one image source. This example uses size=preview, which is covered by your account's 50 free previews a month (up to 10 a day). Node.js 18 or later has fetch and FormData built in, no packages to install.

import { readFile, writeFile } from "node:fs/promises";

const form = new FormData();
form.append("image_file", new Blob([await readFile("photo.jpg")]), "photo.jpg");
form.append("size", "preview");

const res = await fetch("https://api.lassocut.com/v1.0/removebg", {
  method: "POST",
  headers: { "X-Api-Key": process.env.LASSOCUT_API_KEY },
  body: form,
});
if (!res.ok) throw new Error(JSON.stringify(await res.json()));
console.log("credits charged:", res.headers.get("x-credits-charged"));
await writeFile("no-bg.png", Buffer.from(await res.arrayBuffer()));

Tested against the production API on 27 September 2026 with this exact request; it returned a valid PNG.

Run a folder with a promise pool of 3

Promise.all over every file would fire hundreds of uploads at once and hit the rate limit. A pool of three workers pulling from a shared index keeps exactly three requests in flight. Save it as cut.mjs (top-level await needs an ES module) and run node cut.mjs.

import { readdir, readFile, writeFile, mkdir, access } from "node:fs/promises";
import path from "node:path";

const API = "https://api.lassocut.com/v1.0/removebg";
const SRC = "photos", OUT = "out", PARALLEL = 3;
await mkdir(OUT, { recursive: true });

const exists = (p) => access(p).then(() => true, () => false);
const sleep = (s) => new Promise((r) => setTimeout(r, s * 1000));

async function cut(name) {
  const dest = path.join(OUT, path.parse(name).name + ".png");
  if (await exists(dest)) return `skip ${name}`;
  const bytes = await readFile(path.join(SRC, name));
  for (let attempt = 1; ; attempt++) {
    const form = new FormData();
    form.append("image_file", new Blob([bytes]), name);
    form.append("size", "full");
    form.append("format", "png");
    const res = await fetch(API, {
      method: "POST",
      headers: { "X-Api-Key": process.env.LASSOCUT_API_KEY },
      body: form,
    });
    if ((res.status === 429 || res.status === 503) && attempt < 5) {
      await res.body?.cancel();                  // free the connection
      await sleep(Number(res.headers.get("retry-after")) || 2 ** attempt);
      continue;
    }
    if (!res.ok) return `failed ${name}: ${res.status} ${await res.text()}`;
    await writeFile(dest, Buffer.from(await res.arrayBuffer()));
    return `ok ${name} (${res.headers.get("x-credits-charged")} credit)`;
  }
}

const files = (await readdir(SRC)).filter((f) => /\.(jpe?g|png|webp)$/i.test(f));
let next = 0;
async function worker() {
  while (next < files.length) {
    const name = files[next++];
    console.log(await cut(name).catch((e) => `failed ${name}: ${e.message}`));
  }
}
await Promise.all(Array.from({ length: PARALLEL }, worker));
  • Retries: 429 Rate limit exceeded and 503 are retried up to four times. The wait comes from the Retry-After header, in seconds, or doubles from 2 seconds when it is missing. res.body?.cancel() releases the connection before waiting.
  • Skip if done: an image whose out/<name>.png exists is not sent again, so a run stopped halfway, or by a 402 Insufficient credits, resumes where it left off.
  • One failure does not stop the pool: each worker catches its own errors, prints the reason and moves on to the next file.
  • Headers: x-credits-charged gives the cost of each call; x-ratelimit-remaining what is left of the 500 megapixel-images per minute.

The script was run on Node.js 22 against a local test server that answers 429 with Retry-After before succeeding; at most three requests were in flight at any time.

Point an existing Node.js client at LassoCut

Most Node.js remove.bg wrappers hardcode api.remove.bg internally and don't expose a base URL to change, so there is often nothing to reconfigure. The fetch example above is usually the fastest way to switch: it is a dozen lines with no dependency to audit.

If you use a generic HTTP client library that already sends this header and this multipart body to remove.bg (axios, undici, node-fetch), point its base URL at https://api.lassocut.com/v1.0 and keep the same X-Api-Key header; no other code changes are needed.

Useful options

FieldExampleDescription
sizepreview, full, autoPreview costs 0.25 credit; full and 50MP cost 1 credit; auto picks the largest size your balance allows.
formatpng, jpg, webpAuto (default) returns PNG when the result has transparency, JPG otherwise.
typeperson, product, carSelects the model. Auto (default) detects the subject.
crop, crop_margintrue, "30px"Crops the result to the subject, with an optional margin.
bg_color"81d4fa"Fills the background with a hex colour, a colour name, or hex with alpha.

Full list, including framing, shadows and background images: API reference.

Marketplace preset and shadow

A marketplace preset frames the cut-out on the canvas, white background and file size that marketplace expects, and shadow_type=cast adds a cast shadow. The response header X-Compliance says whether the result meets the rules LassoCut checks. With a preset, crop, crop_margin, scale and position are ignored. See marketplace presets.

const form = new FormData();
form.append("image_file", new Blob([await readFile("product.jpg")]), "product.jpg");
form.append("preset", "amazon");
form.append("shadow_type", "cast");
form.append("shadow_angle", "45");

const res = await fetch("https://api.lassocut.com/v1.0/removebg", {
  method: "POST",
  headers: { "X-Api-Key": process.env.LASSOCUT_API_KEY },
  body: form,
});
if (!res.ok) throw new Error(JSON.stringify(await res.json()));
console.log("compliance:", res.headers.get("x-compliance"));
await writeFile("amazon.jpg", Buffer.from(await res.arrayBuffer()));

Common errors

Errors return JSON: {"errors": [{"code": "…", "title": "…"}]}, available from await res.json() when res.ok is false. Nothing is charged on an error.

StatusWhencode
400No image, or two sources givenmissing_source, multiple_sources
402Not enough credits for this sizetitle Insufficient credits
403Missing or wrong X-Api-Keytitles Missing API Key, API Key invalid
429Rate limit reachedtitle Rate limit exceeded, with Retry-After

Full list: API reference.

Next steps

Read the full API reference for every parameter and header, or the migration guide if you're moving code that already calls remove.bg. No key yet? Create a free account, or try LassoCut on your image first, no key required.