Image checker
The checker decides what your file is from its first bytes
When the verdict names a format your file name does not, the reading has not gone wrong. The tool does not consult the extension, the file name or the type the browser reports for the file. It opens the bytes and matches a signature, and everything after that follows from the match.
What the verdict is read from
The checker opens the selected file and compares its leading bytes against a fixed set of signatures. The comparison is written out directly in apps/web/lib/image/inspect.ts, where the JPEG branch reads if (startsWith(bytes, [0xff, 0xd8, 0xff])) return "jpeg";. The file name is not part of that comparison, and neither is the MIME type the browser reports for the file.
This is why a file renamed to .jpg can still be reported as something else. A BMP given a .jpg name does not pass as a JPEG: the name changed, the opening bytes did not, and the opening bytes are the whole of the input.
Attribution for this page: apps/web/lib/image/inspect.ts, apps/web/lib/image/evaluate.ts, apps/web/components/tools/etsy-image-checker.tsx and apps/web/components/tools/product-image-resizer.tsx, read on 2026-08-18 in the feat/expansion-wave-01-continuous working tree.
What gets a vote, and what does not
Four things a seller might reasonably expect to matter, and the weight each one actually carries in the format decision.
- The file's opening bytes
- The input the format decision is made from. Nothing else is compared.
- The file extension
- No weight. A renamed file is judged on its bytes, so the extension can be wrong without changing the result.
- The MIME type the browser reports
- No weight in the format decision. The reader does not take the browser's word for what the file is.
- The file picker's accept setting
- It filters what the operating system dialogue offers, not what the component will judge. Drag and drop and paste can still deliver other types to the tool.
Six signatures are recognised; everything else is unknown
The reader can match PNG, JPEG, GIF, WebP, HEIC and SVG. Those are the signatures it knows.
A file whose opening bytes match none of them is reported as unknown. Unknown is the absence of a match, not a diagnosis: it says the reader could not name the format, and it says nothing about whether the picture inside the file is intact.
Why a WebP file fails this checker
The checker carries its own recorded list of formats. apps/web/lib/image/evaluate.ts holds the finding text that names .jpg, .gif, .png, .svg and .heic as accepted and then states the format the file was read as. A file read as WebP is not on that list, so the finding is a fail.
The picker is a separate matter. It is set to accept every image type, which is why a WebP file can be selected in the first place. Selection is not acceptance: the file is read, the format is named, and then the list is applied. For a WebP file the outcome is a failure every time.
That list is the rule this tool applies, recorded in this tool's own code. It is not a measurement of what any marketplace accepts at upload time today, and this page does not settle that question.
How the animated-GIF verdict is reached, and where it can be wrong
A GIF judged to be animated produces a fail finding titled 'Animated GIFs are not supported' in apps/web/lib/image/evaluate.ts.
The judgement is made by counting Graphic Control Extension blocks inside the file: more than one block, and the file is treated as animated. The code itself describes this count as a heuristic.
It follows that the test can be wrong in the one direction that matters to a seller. A single-frame GIF encoded in an unusual way can, in principle, be counted as animated (inspect.ts:163). If a still export keeps coming back as animated, the finding is describing the structure of the file rather than a picture that moves.
Two tools, two different doors
The checker and the resizer sit in the same repository and do not agree on what may be selected. The picker setting is visible in each component file.
| Tool | What the picker offers | What can still reach the component |
|---|---|---|
| Image checker (apps/web/components/tools/etsy-image-checker.tsx) | Every image type | Anything a picker, a drag and drop or a paste delivers; the format is named after the bytes are read |
| Product image resizer (apps/web/components/tools/product-image-resizer.tsx) | JPEG, PNG and WebP | Other types, by drag and drop or paste; the setting filters the operating system dialogue only |
What this page does not settle
Each of these is a separate question, and none of them is answered by the reading described above.
- What a marketplace accepts at upload time today. The checker applies a list recorded in its own code, and the currency of that list cannot be verified from this surface.
- Whether an image carries transparency, and what the checker reports about it. That is a different examination, settled on its own page.
- Which image files the mobile app accepts. That decision is made on the device before an upload begins, and it is settled on the related page below.
- How long a signed viewing address for a stored image stays valid, and why the extension in a stored key is declared rather than measured. That is a different mechanism, settled on the related page below.
- Which recorded size a file is measured against for a shop banner or a listing slot. The stored numbers are settled on the related guide below.
- What the resizer writes out. The output format and the compression it applies are decided in a module outside the code examined for this page.
- How either tool behaves in a browser that lacks the image facilities they rely on. That was not examined here.
Questions
My file is named .jpg but the checker names a different format. Which one is right?
The verdict describes the bytes; the name describes nothing. The reader compares the file's opening bytes against fixed signatures in apps/web/lib/image/inspect.ts and does not consult the extension or the type the browser reports.
I renamed a file to .jpg and it still failed. Why?
Renaming changes the name and leaves the opening bytes as they were. Since the opening bytes are the only input to the format decision, the same verdict comes back. Re-export the file from the program that produced it instead.
Why was my WebP file refused when the picker let me select it?
The picker is set to accept every image type, so selecting a WebP file is possible. The format list recorded in apps/web/lib/image/evaluate.ts names .jpg, .gif, .png, .svg and .heic, and WebP is not on it, so the finding is a fail. That list is this tool's own rule, not a statement about a marketplace.
How does the checker know my GIF is animated?
It counts Graphic Control Extension blocks inside the file; more than one block produces the fail finding titled 'Animated GIFs are not supported'. The code calls the count a heuristic, and a single-frame GIF encoded in an unusual way can be counted as animated (inspect.ts:163).
What does an unknown format mean?
It means the opening bytes matched none of the six signatures the reader knows: PNG, JPEG, GIF, WebP, HEIC and SVG. It is a statement about the match, not about whether the picture inside the file is intact.