A 400 image_url_fetch_failed error means BackgroundErase tried to download the file from the URL you provided, but the fetch did not succeed. This happens when the API attempts to load image_url and the remote server does not return a successful HTTP 200 response.
In plain terms, the API could not actually retrieve the image from that URL. The most common causes are expired signed links, private storage URLs, missing permissions, bad paths, blocked hotlinking, or links that work in your browser only because you are logged in.
Fastest fix: test the exact image URL outside your app, confirm it returns HTTP 200 and the actual image bytes, then retry the request. If the URL is private or fragile, switch to image_file upload instead.
What this error looks like
A typical response looks like this:
{
"error": {
"code": "image_url_fetch_failed",
"message": "cannot download image_url (HTTP 403)",
"status": 400,
"request_id": "..."
}
}The important part is the HTTP status inside the message. That tells you what the remote server returned when BackgroundErase tried to fetch the URL.
- HTTP 403 usually means forbidden or private access
- HTTP 404 usually means the file path is wrong or the object no longer exists
- HTTP 401 usually means the origin requires authentication
- HTTP 500-series usually means the remote origin itself failed
How image_url works in this API
The image_url field is supported for both JSON and multipart requests. The API downloads the remote file server-side before normal image validation and processing continue.
That means the URL has to work from the server’s point of view, not just from your browser session. If the link only works because your browser already has cookies, a login session, or local network access, BackgroundErase will not be able to fetch it.
The API also accepts imageUrl as an alternate field name in JSON and multipart flows, but the underlying requirement is the same: it has to be a reachable image URL.
Quick checklist
Before changing your app code, walk through this list:
- Open the exact image URL in a private browser window
- Make sure it loads the actual image file, not an HTML page
- Confirm the URL returns HTTP 200
- Make sure the file is publicly reachable without cookies or login
- If using a signed URL, confirm it has not expired
- Retry first with a known-good public image URL
- If needed, switch from image_url to direct file upload
Start with a direct known-good request
The easiest way to isolate the problem is to call the API directly with a URL you know should work. This removes your app, worker, automation builder, and proxy layers from the equation.
JSON example:
curl -H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
https://api.backgrounderase.com/v2 \
-d '{
"image_url": "https://example.com/path/to/image.jpg",
"format": "png",
"size": "full"
}'Multipart example:
curl -H 'x-api-key: YOUR_API_KEY' \
-f https://api.backgrounderase.com/v2 \
-F 'image_url=https://example.com/path/to/image.jpg' \
-F 'format=png' \
-o output.pngA valid JSON request can look like this:
{
"image_url": "https://example.com/path/to/image.jpg",
"format": "png",
"size": "full",
"crop": false,
"despill": false
}The alternate field name imageUrl also works:
{
"imageUrl": "https://example.com/path/to/image.jpg",
"format": "png"
}The most common reasons this fails
In production workflows, these are the most common causes of image_url_fetch_failed:
- The image URL returns 403 because the object is private
- The URL returns 404 because the path is wrong or stale
- The link expired, especially with signed cloud-storage URLs
- The origin requires cookies, auth headers, or a login
- The URL points to a preview page instead of the raw image file
- The origin blocks hotlinking or external fetches
- The file moved after your app stored the original URL
- A redirect chain ends at a page the API cannot use
Browser success does not always mean server success
One of the most common debugging mistakes is testing the URL in a browser tab and assuming that means the API can fetch it too. Browsers often have cookies, active sessions, and access to internal network contexts that a server-side fetch does not have.
So the real question is not “does it open for me?” The real question is “does this exact URL return a direct HTTP 200 image response without any browser state?”
Good test: open the link in a private browsing window, or fetch it from a script without any saved session or cookies.
Check the URL response directly
Before you debug your app, inspect the remote URL itself. First check the headers:
curl -I "https://example.com/path/to/image.jpg"Then inspect it more fully in Python:
import requests
url = "https://example.com/path/to/image.jpg"
response = requests.get(url, timeout=15, allow_redirects=True)
print("Status:", response.status_code)
print("Content-Type:", response.headers.get("Content-Type"))
print("Final URL:", response.url)
print("Bytes:", len(response.content))Or in Node.js:
const response = await fetch("https://example.com/path/to/image.jpg", {
redirect: "follow"
});
console.log("Status:", response.status);
console.log("Content-Type:", response.headers.get("content-type"));
console.log("Final URL:", response.url);Watch out for preview pages and redirects
A very common failure mode is using a URL that looks like an image link in the browser but is actually a preview page, file-sharing page, or HTML wrapper. In those cases the browser may render something that looks correct, but the API is not fetching the raw image object the way you expect.
Redirects can cause similar confusion. A shared link may redirect through a preview system, an expiring download endpoint, or a login page. If the final server response is not what the API can use, the request will fail.
Best practice: use direct object URLs or stable signed URLs that point straight to the image bytes rather than human-facing share pages.
Signed URLs are a frequent cause
If your product stores images in S3, GCS, Cloudflare R2, or another object store, signed URLs are often the right tool. But they can also produce image_url_fetch_failed if they expire before BackgroundErase fetches them or if the signature was generated incorrectly.
When this happens, the fastest test is to generate a fresh signed URL and call the API immediately. If that works, the problem is probably URL lifetime or signing logic rather than BackgroundErase itself.
When to switch to direct upload instead
If your image URLs are private, short-lived, user-session dependent, or hard to keep stable, direct file upload is often the better integration pattern. Using image_file avoids remote fetch problems entirely because the image bytes are sent straight to the API with the request.
This is especially helpful in server-side pipelines, worker jobs, and SaaS backends where you already have the image file in hand after upload.
image_url_fetch_failed vs body is not a valid image
These two issues are related but different. If the remote server returns a non-200 status, you will usually see image_url_fetch_failed. But if the remote URL returns HTTP 200 and the body is not actually an image, the API may get past the fetch step and then fail later when it tries to decode the body as an image.
That is why checking both status code and content type matters. A URL that returns 200 with HTML is still not a valid image source.
Final resolution path
If you are seeing image_url_fetch_failed, the cleanest path is:
- Test the exact URL outside your app
- Confirm it returns HTTP 200
- Confirm it points to the actual image file
- Make sure it does not require login or cookies
- Regenerate the link if it is signed or expiring
- Retry with a minimal direct API request
- Use image_file upload if the URL path is too fragile
In most cases, the fix is not in the BackgroundErase options. It is in the accessibility and stability of the remote image URL itself.
