API

Remove Image Backgrounds in C# / .NET with an API (HttpClient, MultipartFormDataContent)

September 6, 20265 min readBy BG Clear Editorial

In .NET the fastest reliable way to remove an image background is an API call: HttpClient already does multipart, System.Text.Json handles the response, and IHttpClientFactory plus Polly turns it into something production-safe. This tutorial builds a small typed client for the bgclear API, wires it into ASP.NET Core, and adds an endpoint so your Blazor or JavaScript front end never sees the key. remove.bg users: the request fields are identical, which is useful with remove.bg's API ending on 1 December 2026.

In this guide

A typed client

using System.Net.Http.Headers;
using System.Text.Json;

public sealed class BgClearClient(HttpClient http)
{
    // http.BaseAddress = https://www.bgclear.ai/api/v1/ and the Authorization
    // header are configured in Program.cs (see below).

    public async Task<byte[]> RemoveBackgroundAsync(Stream image, string fileName,
        string size = "auto", string format = "png", string? bgColor = null,
        string? idempotencyKey = null, CancellationToken ct = default)
    {
        using var form = new MultipartFormDataContent();
        var file = new StreamContent(image);
        file.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
        form.Add(file, "image_file", fileName);
        form.Add(new StringContent(size), "size");        // preview (free) | full | auto
        form.Add(new StringContent(format), "format");    // png | webp | jpg
        if (bgColor is not null) form.Add(new StringContent(bgColor), "bg_color");

        using var req = new HttpRequestMessage(HttpMethod.Post, "remove") { Content = form };
        if (idempotencyKey is not null) req.Headers.Add("Idempotency-Key", idempotencyKey);

        using var res = await http.SendAsync(req, ct);
        if (!res.IsSuccessStatusCode)
        {
            var err = await JsonSerializer.DeserializeAsync<ErrorEnvelope>(await res.Content.ReadAsStreamAsync(ct), cancellationToken: ct);
            throw new BgClearException((int)res.StatusCode, err?.Error?.Code ?? "unknown", err?.Error?.Message ?? "");
        }
        Console.WriteLine($"credits remaining: {res.Headers.GetValues("X-Credits-Remaining").FirstOrDefault()}");
        return await res.Content.ReadAsByteArrayAsync(ct);
    }

    public async Task<RemoveResult> RemoveByUrlAsync(string imageUrl, string size = "auto", CancellationToken ct = default)
    {
        using var req = new HttpRequestMessage(HttpMethod.Post, "remove")
        {
            Content = JsonContent.Create(new { image_url = imageUrl, size, format = "webp" })
        };
        req.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        using var res = await http.SendAsync(req, ct);
        res.EnsureSuccessStatusCode();
        return (await res.Content.ReadFromJsonAsync<RemoveResult>(cancellationToken: ct))!;
    }
}

public record RemoveResult(string Id, string Url, int Width, int Height, int Credits_Charged, int Credits_Remaining, int Processing_Ms);
public record ErrorEnvelope(ErrorBody? Error);
public record ErrorBody(string Code, string Message, string Docs);
public class BgClearException(int status, string code, string message) : Exception($"{status} {code}: {message}")
{
    public int Status { get; } = status;
    public string Code { get; } = code;
}

RemoveByUrlAsync returns a hosted result URL valid for 24 hours — handy when the next step is a CDN upload rather than a local file.

Registration with IHttpClientFactory and Polly

// Program.cs
builder.Services.AddHttpClient<BgClearClient>(client =>
{
    client.BaseAddress = new Uri("https://www.bgclear.ai/api/v1/");
    client.DefaultRequestHeaders.Authorization =
        new AuthenticationHeaderValue("Bearer", builder.Configuration["BgClear:ApiKey"]);
    client.Timeout = TimeSpan.FromSeconds(90);
})
.AddStandardResilienceHandler(o =>
{
    // 429 and 5xx are retried with backoff; 4xx are not.
    o.Retry.ShouldHandle = args => ValueTask.FromResult(
        args.Outcome.Result is { StatusCode: System.Net.HttpStatusCode.TooManyRequests }
        || (int?)args.Outcome.Result?.StatusCode >= 500);
    o.Retry.MaxRetryAttempts = 4;
    o.Retry.Delay = TimeSpan.FromSeconds(5);
});

Keep the key in user-secrets or an environment variable (BgClear__ApiKey), never in appsettings.json committed to git. The rate limit is 60 requests a minute per key; the resilience handler's backoff covers a burst.

A minimal API endpoint for your front end

app.MapPost("/api/cutout", async (IFormFile image, BgClearClient bgclear, CancellationToken ct) =>
{
    if (image.Length > 25 * 1024 * 1024) return Results.BadRequest("Max 25 MB");
    await using var stream = image.OpenReadStream();
    try
    {
        var png = await bgclear.RemoveBackgroundAsync(stream, image.FileName,
            size: "auto", idempotencyKey: $"{image.Length}-{image.FileName}", ct: ct);
        return Results.File(png, "image/png");
    }
    catch (BgClearException e) when (e.Status == 402)
    {
        return Results.Problem("Out of credits", statusCode: 402);
    }
})
.DisableAntiforgery()
.RequireAuthorization();

The RequireAuthorization() matters: without it, anyone who finds the endpoint spends your credits. Images above 4 megapixels at full size are rejected synchronously; send those to jobs and poll jobs/{id}, or pass an X-Callback-Url header — the bulk guide has the pattern.

Cost and testing

size=preview is free and unlimited — use it in integration tests. Full-resolution images cost one credit ($9 for 100, $39 for 500, $129 for 2,000; credits never expire, failures never charged — pricing). Replacing remove.bg? Same fields, new URL and header: migration page.

Frequently asked questions

Is there a NuGet package?

No — the typed client above is the whole thing, and you can generate one from the OpenAPI document at /api/v1/openapi.json with NSwag or Kiota if you prefer.

Can I use this from a Blazor WebAssembly app directly?

Only through your own server endpoint; the key must never reach the browser.

Does it work on .NET Framework?

Yes with HttpClient and MultipartFormDataContent (available since .NET Framework 4.5); drop the primary-constructor syntax and the resilience handler.

What does a full-resolution image cost?

One credit — $0.065 to $0.09 depending on pack; previews are free.

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

Background Removal API Free

background removal api free

Canva Background Remover Alternative

canva background remover alternative

Cheapest Background Remover API

cheapest background remover api

Keep reading

API

Remove Image Backgrounds in Java and Spring Boot with an API (HttpClient, RestClient)

Java 11+ HttpClient with a JSON/base64 body (no multipart boilerplate), Spring's RestClient with MultipartBodyBuilder, error mapping, and a @Async service for catalogues.

API

Remove Image Backgrounds in Node.js with fetch and FormData (No SDK)

Node 18+ built-in fetch, a file upload, a URL input, an Express proxy endpoint so your browser never sees the key, and retries that cannot double-charge.

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

7 remove.bg API Alternatives Compared (2026): Price per Image, Free Tier, Drop-in Compatibility

With remove.bg closing on 1 Dec 2026, here is what the alternatives actually charge per image, what you get free, and which ones let you keep your existing request code.