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.

ToolWhat the picker offersWhat can still reach the component
Image checker (apps/web/components/tools/etsy-image-checker.tsx)Every image typeAnything 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 WebPOther 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.