You Downloaded a .webp and Nothing Opens It. What Happened and 3 Ways Out
You see a product photo, right-click, "Save image as", and get image.webp. Your upload form rejects it, an older editor can't open it, and the person you sent it to asks what a WebP is. The website probably never "uploa
You see a product photo, right-click, "Save image as", and get image.webp. Your upload form rejects it, an older editor can't open it, and the person you sent it to asks what a WebP is.
The website probably never "uploaded a WebP". Your browser asked for one.
How you ended up with WebP
When a browser requests an image, it sends an Accept header listing formats it understands, including image/webp and often image/avif. Most image CDNs read that header and send the smallest format the browser supports. The store owner uploaded a JPG. The CDN converted it on the fly, and "Save image as" saved what actually arrived.
I wrote about this in more detail in Your Image CDN Picks the Format, including how to see what a CDN really sends.
WebP itself is a good format. Lossy WebP is usually smaller than a JPEG of similar quality, and it supports transparency, which JPEG doesn't. The problem is only compatibility outside the browser: some desktop apps, print services and upload validators still expect JPG or PNG.
Check what the file really is
Extensions lie in both directions. Look at the first 12 bytes:
async function realType(file) {
const b = new Uint8Array(await file.slice(0, 12).arrayBuffer())
const s = (i, j) => String.fromCharCode(...b.subarray(i, j))
if (s(0, 4) === "RIFF" && s(8, 12) === "WEBP") return "webp"
if (b[0] === 0xff && b[1] === 0xd8 && b[2] === 0xff) return "jpeg"
if (s(1, 4) === "PNG") return "png"
if (s(4, 8) === "ftyp") return "heic/avif family" // check the brand at 8-12
return "unknown"
}
A WebP always starts with RIFF, four size bytes, then WEBP. If your "photo.jpg" starts that way, it's a WebP with the wrong name, and some programs will refuse it for exactly that reason.
Way out 1: ask for a JPG instead
Because the CDN decided by the Accept header, you can often get the original format by asking without WebP in the list. Copy the image address and:
curl -s -o photo.jpg -H "Accept: image/jpeg" "https://example.com/path/to/image"
Then check the bytes with the function above. This works on many CDNs, not all. Some serve WebP whatever you ask, and some URLs point to a WebP original.
Way out 2: convert to JPG
For photos going to upload forms, email or print, JPG is the safe choice. One thing to get right: JPEG has no transparency. Any transparent pixels have to become a colour, and if a converter doesn't choose one, many viewers show them as black. Fill with white first:
async function webpToJpg(file, quality = 0.9) {
const bitmap = await createImageBitmap(file)
const canvas = new OffscreenCanvas(bitmap.width, bitmap.height)
const ctx = canvas.getContext("2d")
ctx.fillStyle = "#ffffff"
ctx.fillRect(0, 0, canvas.width, canvas.height)
ctx.drawImage(bitmap, 0, 0)
bitmap.close()
return canvas.convertToBlob({ type: "image/jpeg", quality })
}
Way out 3: convert to PNG when transparency matters
Logos, icons and cut-out product shots often use transparency. Converting those to JPG puts a white box behind them. Use PNG instead: it's lossless and keeps the alpha channel. The file will be bigger than the WebP, sometimes several times bigger, because PNG doesn't use lossy compression. That's the price of an exact copy.
Quick rule:
| You have | Going to | Pick |
|---|---|---|
| A photo | Form, email, print | JPG |
| A logo or cut-out | Editing, design tools | PNG |
| Anything | Your own website | Keep WebP |
If you have many
Converting one file in an editor is fine. For a folder of them, BatchSet has free converters for WebP to JPG (transparent areas filled with white) and WebP to PNG (transparency kept). Both run in the browser, so the images aren't uploaded, and you download everything as one ZIP.
This article was drafted with an AI assistant. The byte check was tested against real WebP, PNG and JPEG files before publishing.
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.