JPEG file format
A lossy-compressed raster image format, ubiquitous for photos.
- MIME type
- image/jpeg
- Extensions
- .jpg, .jpeg
- Category
- Images
Magic-number signature
| 0x00000000 | FFD8FF | ··· | Start-Of-Image marker |
About the JPEG format
JPEG uses discrete-cosine-transform compression tuned for photographic images, trading a small, mostly invisible amount of quality for a large drop in file size. Files begin with the Start-Of-Image marker FF D8 and end with FF D9. Everything between those two markers is a chain of segments, each introduced by FF followed by a marker byte, and almost all of them carry a two-byte big-endian length right after the marker — which is what lets a parser walk a JPEG without understanding a single one of its segments. The pixel data itself lives in the entropy-coded stream after the Start-Of-Scan marker, and that stream is the one part of the file with no length field at all: a decoder finds its end by scanning for the next real marker.
Header layout, byte by byte
| Offset | Length | Field | Meaning |
|---|---|---|---|
| 0 | 2 | Start of Image marker | FF D8. One of the handful of markers that carry no length and no payload. The catalog signature reads three bytes rather than two because the FF that opens the next marker follows immediately, and requiring it rules out a file that happens to start with FF D8 by accident. |
| 2 | 2 | First application marker | FF E0 introduces APP0 and means the file follows JFIF; FF E1 introduces APP1 and usually means Exif. Cameras and phones write APP1, image editors tend to write APP0 first and APP1 after it, and a file with both is completely normal. |
| 4 | 2 | Segment length | Big-endian byte count of the segment, counting these two bytes but not the two marker bytes before them. An APP0 with no thumbnail reads 00 10 — sixteen — so the next marker starts at 4 plus 16, which is offset 20. |
| 6 | 5 | JFIF identifier | 4A 46 49 46 00, the ASCII letters JFIF and a NUL. When APP1 came first instead, offset 6 holds the six bytes 45 78 69 66 00 00 and the whole segment is Exif rather than JFIF. |
| 11 | 2 | JFIF version | Major then minor as two single bytes: 01 01 is version 1.01, 01 02 is 1.02. Present only when APP0 is the first segment; in an Exif-first file these bytes are part of the TIFF structure instead. |
| 13 | 1 | Density units | 0 means the density numbers express only an aspect ratio, 1 means dots per inch, 2 means dots per centimetre. Plenty of encoders write 0 here and then still fill in 72 and 72, which is why print sizes derived from a JPEG are so often meaningless. |
| 14 | 4 | Horizontal and vertical density | Two big-endian 16-bit numbers, X then Y, interpreted by the units byte before them. This is the JFIF answer to what a PNG stores in pHYs, and the two are not kept in sync by anything. |
| 18 | 2 | Thumbnail width and height | One byte each, almost always 00 00. If they are not zero, three times width times height bytes of uncompressed RGB follow at offset 20 and the segment length at offset 4 grows to match — an easy consistency check by hand. |
| -2 | 2 | End of Image marker | FF D9, and like the SOI it has no length. Trailing bytes after it are legal enough that decoders ignore them, which is how ZIP archives and shell scripts get smuggled into image files. |
Telling it apart from its neighbours
| Easily confused with | How to tell |
|---|---|
| JFIF/Exif | Both are JPEG, and the split is decided entirely by the marker at offset 2. FF E0 with 4A 46 49 46 00 at offset 6 is JFIF, and everything you can learn from it is the density pair. FF E1 with 45 78 69 66 00 00 at offset 6 is Exif, and at offset 12 a complete TIFF header begins — 49 49 2A 00 or 4D 4D 00 2A, then a four-byte offset to the first directory. That is where camera model, exposure, orientation and GPS live. A file can carry both segments, in which case the Exif one is the one worth reading. |
| HEIC | The two formats compete for the same job on the same phones, and the setting that switches between them is one toggle deep in the camera app. JPEG is FF D8 FF at offset 0. HEIC has nothing at offset 0 but a box length, and reads 66 74 79 70 68 65 69 63 at offset 4. Photos exported from an iPhone in Most Compatible mode are JPEG, everything else is HEIC. |
| PNG | FF D8 FF against 89 50 4E 47. Worth checking rather than trusting the extension, because a JPEG saved as .png stays a JPEG and every browser renders it anyway, and because re-encoding a screenshot to JPEG is the single most common reason text in an image goes fuzzy. |
| JPEG 2000 | A different codec that only shares a name. A raw JPEG 2000 codestream begins FF 4F FF 51; the boxed JP2 file form begins 00 00 00 0C 6A 50 20 20 0D 0A 87 0A. Neither will decode in a browser, which is why a .jp2 downloaded from a scientific or archival source appears broken. |
How these files break
- Truncation. The header survives so a viewer knows the dimensions and paints the top of the picture, then the entropy-coded stream runs out and the rest of the frame stays grey or repeats the last block. The tell is the last two bytes: an intact JPEG ends FF D9.
- A byte inserted or dropped inside the scan data. Huffman coding has no byte alignment to resynchronise against, so every block after the damage decodes with the wrong DC prediction and the image dissolves into shifted colour bands from that row down. Unless the encoder wrote restart markers, nothing recovers.
- Text-mode transfer. The same line-ending translation that ruins a PNG rewrites 0D 0A inside compressed data here too, and JPEG has no per-segment checksum to notice. The file opens, the header is perfect, and the bottom two-thirds are smeared.
- A broken Exif directory. The APP1 segment length is right but an offset inside the TIFF structure points past the end of the segment, so photos lose their orientation tag and appear rotated ninety degrees in some apps and upright in others. Stripping the segment fixes the display and destroys the metadata.
- Bytes prepended by a server error page or a stray BOM. FF D8 FF is no longer at offset 0, so strict decoders reject the file outright while lenient ones scan forward and open it, producing the familiar situation where an image works in the browser and fails in the build.
Where the format stands today
JPEG is thirty years old and still the format almost every photograph on the internet is delivered in. Nothing else is decoded by literally every camera, phone, browser, printer, scanner and photo frame ever made, and that universality is worth more than the twenty to fifty percent that WebP, AVIF and HEIC would save. Where it genuinely loses is anything with hard edges — screenshots, diagrams, text, line art — because the block transform smears exactly the high-frequency detail those images are made of, and anything that will be edited and saved repeatedly, since every save is a fresh lossy encode and the damage accumulates. It has no alpha channel at all, so a logo that needs transparency cannot be a JPEG. The intended successor, JPEG XL, offers lossless recompression of existing JPEGs and better quality per byte, but browser support stalled and it is not a delivery option today. In practice the modern answer is to keep JPEG as the fallback inside a picture element and serve WebP or AVIF to everything that will take them.
Open JPEG files on this site
Every one of these runs in your browser — the file never leaves your machine.
Related formats
Formats that are easy to confuse with JPEG — compare their leading bytes.