API

WooCommerce: Remove Product Image Backgrounds Automatically (WP-CLI Command + API)

September 6, 20266 min readBy BG Clear Editorial

WooCommerce stores rarely have studio photography for every SKU; they have supplier photos on beige tables and phone shots on the shop floor. The fix does not need a plugin subscription: a 60-line mu-plugin that adds a WP-CLI command, sends each product image to a background removal API with a white fill, sideloads the result into the media library and sets it as the product image. Run it once for the catalogue, then on new products.

In this guide

The mu-plugin

Save as wp-content/mu-plugins/bgclear-woo.php. It uses wp_remote_post with a JSON body (image_file_b64), so there is no multipart code and no cURL dependency, and it keeps the originals — the cutout is added as a new attachment.

<?php
/**
 * Plugin Name: bgclear for WooCommerce (WP-CLI)
 * Description: wp bgclear products — white-background product images via the bgclear API.
 */
if (!defined('WP_CLI') || !WP_CLI) { return; }

class BgClear_Woo_Command {
    /**
     * Process product images. [--dry-run] uses free preview size. [--limit=<n>]
     */
    public function products($args, $assoc) {
        $key   = defined('BGCLEAR_API_KEY') ? BGCLEAR_API_KEY : getenv('BGCLEAR_API_KEY');
        $size  = isset($assoc['dry-run']) ? 'preview' : 'full';
        $limit = (int) ($assoc['limit'] ?? 100);
        require_once ABSPATH . 'wp-admin/includes/media.php';
        require_once ABSPATH . 'wp-admin/includes/file.php';
        require_once ABSPATH . 'wp-admin/includes/image.php';

        $products = wc_get_products(['limit' => $limit, 'status' => 'publish']);
        foreach ($products as $product) {
            if ($product->get_meta('_bgclear_done')) { continue; }
            $thumb_id = $product->get_image_id();
            $path = $thumb_id ? get_attached_file($thumb_id) : null;
            if (!$path || !file_exists($path)) { continue; }

            $res = wp_remote_post('https://www.bgclear.ai/api/v1/remove', [
                'timeout' => 90,
                'headers' => [
                    'Authorization'   => 'Bearer ' . $key,
                    'Content-Type'    => 'application/json',
                    'Accept'          => 'application/json',
                    'Idempotency-Key' => 'woo-' . $thumb_id . '-' . md5_file($path),
                ],
                'body' => wp_json_encode([
                    'image_file_b64' => base64_encode(file_get_contents($path)),
                    'size' => $size, 'format' => 'jpg', 'bg_color' => 'ffffff',
                ]),
            ]);
            $code = wp_remote_retrieve_response_code($res);
            $data = json_decode(wp_remote_retrieve_body($res), true);
            if ($code !== 200) {
                WP_CLI::warning(sprintf('#%d %s: %s', $product->get_id(), $code, $data['error']['message'] ?? 'error'));
                if ($code === 402) { WP_CLI::error('Out of credits — https://www.bgclear.ai/api-pricing/'); }
                continue;
            }

            // Sideload the hosted result (valid 24 h) into the media library.
            $new_id = media_handle_sideload(
                ['name' => $product->get_slug() . '-white.jpg', 'tmp_name' => download_url($data['url'])],
                $product->get_id(), $product->get_name() . ' on white background'
            );
            if (is_wp_error($new_id)) { WP_CLI::warning($new_id->get_error_message()); continue; }

            $product->set_image_id($new_id);
            $product->update_meta_data('_bgclear_done', current_time('mysql'));
            $product->save();
            WP_CLI::log(sprintf('#%d %s → attachment %d (credits left %s)',
                $product->get_id(), $product->get_name(), $new_id, $data['credits_remaining'] ?? '?'));
        }
        WP_CLI::success('Done.');
    }
}
WP_CLI::add_command('bgclear', 'BgClear_Woo_Command');

Define the key in wp-config.php (define('BGCLEAR_API_KEY', '…');) or the environment, never in the plugin file.

Running it

# free dry run on 20 products — preview size, no credits used
wp bgclear products --dry-run --limit=20

# the real thing
wp bgclear products --limit=500

The _bgclear_done meta flag makes the command resumable and prevents double processing; the idempotency header makes a retry of an interrupted request free for 24 hours. Gallery images: loop $product->get_gallery_image_ids() the same way and call set_gallery_image_ids() with the new ids.

On upload instead of in bulk

To process new product images as they are added, hook woocommerce_admin_process_product_object (fires on product save in wp-admin) and call the same request for the product's image id when _bgclear_done is empty. Do it via wp_schedule_single_event or Action Scheduler rather than inline — a 5-second API round trip inside the save request is where editors get impatient.

Why JPG on white, and what it costs

Marketplace feeds (Google Shopping, Meta, Amazon) and most themes expect a solid white main image, and JPG on white is a fraction of the size of a transparent PNG, which helps Core Web Vitals on category pages. If your theme uses coloured cards, request format: 'png' without bg_color for a transparent cutout instead.

Cost: one credit per full-resolution image — $9 for 100, $39 for 500, $129 for 2,000; credits never expire, and the dry run is free (pricing). Stores that used a remove.bg plugin should note its API ends on 1 December 2026; the request above is field-compatible, see the migration page.

Frequently asked questions

Is there a plugin I can install instead?

This mu-plugin is the plugin: one file, no settings screen, runs from WP-CLI. Managed hosts that block WP-CLI can run the same code from a custom admin action or a cron event.

Will this overwrite my original product images?

No. The cutout is added as a new attachment and set as the product image; the original stays in the media library.

Does it work with large supplier images?

Synchronous full-size requests are capped at 4 megapixels. Resize on upload (WordPress's big_image_size_threshold does this by default at 2560 px) or route larger files through POST /api/v1/jobs.

What does it cost for a 300-product store?

300 credits — the $39 pack covers 500 images at $0.078 each, and the remaining credits never expire.

Ship it with the bgclear API

remove.bg-compatible endpoints, credits from $9 for 100 images, no subscription. Pay, get a key, make your first call in under two minutes.

Get API credits →

Tools for this guide

How to Get White Background in Product Photos

how to get white background in product photos

White Background Product Photo Online

white background product photo online

Aadhaar Photo Background White

aadhaar photo background white

Keep reading

API

Shopify: Give Every Product Photo a White Background Automatically (Admin API + Background Removal API)

A script that walks your Shopify catalogue, sends each image through a background removal API with a white fill, and re-attaches the result with productCreateMedia — no app, no manual editing.

API

Remove Image Backgrounds in PHP and Laravel with an API (cURL, Guzzle, Http Client)

Plain PHP with cURL, Guzzle multipart, Laravel's Http client with attach(), a queued job for bulk, and the two-line change if you used the remove.bg PHP package.

API

Bulk Background Removal via API: Async Jobs, Batches of 50 and Webhooks

How to process a catalogue of thousands of images without babysitting a script: batch submission, callbacks instead of polling, credit accounting, and what to do when the queue is full.

API

Automate Background Removal in n8n, Zapier and Make (No Code)

Exact node-by-node settings to remove backgrounds inside an automation: HTTP Request node in n8n, Webhooks by Zapier, and Make's HTTP module — then send the cutout to Drive, Shopify or Airtable.