The smallest transparent GIF is 43 bytes.
This is all of it. Pick any byte to see what it does, then copy the file, download it, hotlink it, or serve it from your own code.

What every byte does
A GIF is a sequence of blocks. This one has seven, and every colour on this page belongs to one of them. Select a byte or a block to read it. Numbers are stored little-endian: the low byte comes first, so 01 00 means 1.
| Bytes | Field | Meaning |
|---|---|---|
| Header Tells the decoder this is a GIF and which version of the format to expect. | ||
| 47 49 46 | Signature | The ASCII letters “GIF”. Every GIF file starts with them. |
| 38 39 61 | Version | “89a”. 89a is needed for transparency; 87a has no graphic control extension. |
| Logical screen descriptor The size of the canvas and how its colour table is set up. | ||
| 01 00 | Canvas width | 1 px. |
| 01 00 | Canvas height | 1 px. |
| 80 | Packed flags | Four settings squeezed into one byte. The top bit says a global colour table follows; the last three bits give its size. |
| 00 | Background colour index | Palette entry 0. Browsers ignore it and show what is behind the image. |
| 00 | Pixel aspect ratio | 0 means square pixels, with no correction. |
| Global colour table The palette. Pixels store an index into this list instead of a colour. | ||
| FF FF FF | Palette entry | Red, green and blue, one byte each: #ffffff. Two entries is the smallest table a GIF can have. |
| 00 00 00 | Palette entry | Red, green and blue, one byte each: #000000. Two entries is the smallest table a GIF can have. |
| Graphic control extension Optional block added in GIF89a. Here it makes palette entry 0 transparent. | ||
| 21 | Extension introducer | 0x21 (“!”) announces an extension block. |
| F9 | Graphic control label | 0xF9 says this extension is a graphic control extension. |
| 04 | Block size | 4 bytes of settings follow. |
| 01 | Packed flags | The lowest bit is the transparency flag. It is on, so the transparent index below is used. |
| 00 00 | Delay | 0 hundredths of a second. It only matters for animations. |
| 00 | Transparent colour index | Palette entry 0 is drawn as fully transparent. |
| 00 | Block terminator | A zero-length sub-block that closes the block. |
| Image descriptor Where the image sits on the canvas and how big it is. | ||
| 2C | Image separator | 0x2C (“,”) starts an image. |
| 00 00 | Left | The image starts 0 px from the left edge of the canvas. |
| 00 00 | Top | The image starts 0 px from the top edge of the canvas. |
| 01 00 | Image width | 1 px. |
| 01 00 | Image height | 1 px. |
| 00 | Packed flags | No local colour table, not interlaced. The image uses the global palette. |
| Image data The pixels, compressed with LZW and split into sub-blocks of up to 255 bytes. | ||
| 02 | LZW minimum code size | 2, so compressed codes start 3 bits wide. |
| 02 | Sub-block size | 2 bytes of compressed data follow. |
| 44 01 | Compressed pixels | LZW codes packed from the lowest bit up. See how they decode below. |
| 00 | Block terminator | A zero-length sub-block that closes the block. |
| Trailer One byte that marks the end of the file. | ||
| 3B | Trailer | 0x3B (“;”) ends the file. |
Inside the packed bytes
Three bytes each store several small settings. Bit 7 is the leftmost.
0x800x010x00How two bytes hold one pixel
With a minimum code size of 2, the decoder reads 3-bit codes. Code 4 clears the table, code 5 ends the image, and codes 0 to 3 are palette entries. The bytes 44 01 are read from the lowest bit up:
0x44 010001000x01 00000001
- 001100 = 4Clear: start with a fresh table
- 000000 = 0Pixel: palette entry 0
- 101101 = 5End of image
- 0000000 Unused padding bits
Bigger images use the same trick: every new code stands for a run one pixel longer than the last, so a 1000×1000 transparent GIF takes only 1,743 bytes.
Can it be smaller?
Yes, if you drop parts that decoders tolerate losing. We fed each variant to three browser engines and to Pillow and recorded what they drew.
| Size | Variant | Chromium | Firefox | WebKit | Pillow |
|---|---|---|---|---|---|
| 43 | The standard file on this page. | Transparent | Transparent | Transparent | Transparent |
| 42 | No trailer byte. Decoders stop at the end of the data anyway. | Transparent | Transparent | Transparent | Transparent |
| 37 | No palette at all. Still valid: the spec lets decoders use their own palette, and index 0 is transparent anyway. | Transparent | Transparent | Transparent | Transparent |
| 36 | No palette and no trailer. | Transparent | Transparent | Transparent | Transparent |
| 35 | No transparency block: the pixel is drawn in palette colour 0, white. | White | White | White | White |
| 35 | The 1987 format. It has no way to mark a colour transparent. | White | White | White | White |
| 34 | Transparency block but no compressed pixels. | Transparent | Transparent | Transparent | Error |
| 33 | The same without the trailer. | Transparent | Transparent | Transparent | Error |
| 29 | No palette and no transparency. Each engine picks its own colour. | Black | White | Transparent | Black |
| 26 | An image with no compressed data at all. | Transparent | Transparent | Transparent | Error |
| 14 | Header, canvas size and trailer only. There is no image in it. | Transparent | Error | Transparent | Error |
Use 43 bytes when it must work everywhere. 37 bytes is still valid GIF and was transparent in every engine we tested. Below that you depend on decoder leniency, and the 29-byte file shows how engines disagree.
Checked on September 23, 2026 with Chromium 153.0.8010.12, Firefox 155.0, WebKit 26.6, Pillow 12.2.0.
Make one any size
Transparent or a solid colour, from 1×1 up to 65535×65535. It is generated in your browser; nothing is uploaded.
Hotlink it
Link straight to these files from any site, email or app. They are served from Cloudflare's edge with long cache lifetimes, and CORS is open to everyone.
- The 43-byte file
https://emptygif.com/1x1.gif - Any size, transparent
https://emptygif.com/px/300x250.gif - Any size, solid colour
https://emptygif.com/px/300x250/ff5a1f.gif - JSON API: size, base64 and data URI
https://emptygif.com/api/gif?w=300&h=250 - Every snippet as JSON
https://emptygif.com/snippets.json - Summary for AI agents
https://emptygif.com/llms.txt
Response headers
HTTP/2 200
content-type: image/gif
content-length: 43
cache-control: public, max-age=31536000, immutable
access-control-allow-origin: *
cross-origin-resource-policy: cross-origin
timing-allow-origin: *Example
<img src="https://emptygif.com/1x1.gif" width="1" height="1" alt="">
Generated sizes go up to 4096 px per side. Please download and self-host the file if you serve heavy traffic.
Serve it from your stack
191 ready-to-run snippets. Pick yours: each one answers at the path you choose with an image/gif response. If you changed the size or colour above, the snippets use that GIF.
JavaScript & TypeScript
- Next.js (App Router)
- Hono
- Bun.serve
- Elysia
- Deno.serve
- SvelteKit
- Nuxt (Nitro server route)
- Astro
- React Router (framework mode, ex-Remix)
- TanStack Start
- SolidStart
- Hono on Bun
- Hono on Deno
- srvx (universal fetch server)
- Qwik City
- RedwoodSDK
- Angular SSR (Express server.ts)
- Fresh
- Oak
- Encore.ts
- NestJS
- Fastify
- Express
- Node.js standard library (node:http)
- Koa
- hapi
- AdonisJS
Edge & serverless
- Cloudflare Workers
- Cloudflare Workers (Rust, workers-rs)
- Cloudflare Pages Functions
- Spin (Rust, WASI HTTP component)
- Deno Deploy (deno serve)
- Vercel Functions
- Netlify Functions
- Netlify Edge Functions
- AWS Lambda (Node.js)
- AWS Lambda (Python)
- AWS Lambda (Go)
- AWS Lambda (Rust, lambda_http)
- AWS Lambda@Edge (CloudFront)
- Google Cloud Run functions (Node.js)
- Google Cloud Run functions (Python)
- Firebase Cloud Functions + Hosting
- Azure Functions (Node.js v4 model)
- Fastly Compute (JavaScript)
Python
Go
JVM
PHP
Elixir, Erlang & Gleam
Functional languages
C, C++ & systems languages
Swift, Dart & other languages
Web servers & proxies
Command line & one-liners
Express JavaScript
import express from 'express';
const GIF = Buffer.from('R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==', 'base64');
const app = express();
app.get('/pixel.gif', (req, res) => {
res.set('Cache-Control', 'no-store');
res.type('gif').send(GIF);
});
app.listen(8080);
We ran this snippet and compared the bytes it returned. Open page
What it is used for
- Tracking pixels and beacons: the server logs the request and answers with the smallest valid image.
- Placeholders for lazy-loaded images, so the
imgtag is valid before the real source arrives. - Fixed-size spacers in HTML email, where CSS support is patchy.
- Tests and mocks that need a real image without shipping one.
Tracking pixels are less reliable than they look
Apple Mail preloads remote images through a proxy when Mail Privacy Protection is on, so an “open” may never have been a person. Gmail also fetches images through its own proxy and caches them. Many clients block remote images by default. For page analytics, navigator.sendBeacon() or a 204 No Content response is often a better fit than an image.
Questions
- Why is it called empty when it has a pixel?
- A GIF must have at least one pixel. This one is 1×1 and its only colour is marked transparent, so nothing shows.
- Is the 43-byte file valid?
- Yes. It follows the GIF89a specification exactly, and every engine in the table above draws it as transparent.
- Why a GIF and not a PNG or WebP?
- It is smaller than a minimal transparent PNG, and every browser, email client and image library from the last 35 years can read it.
- Should I use a data URI or a file?
- A data URI saves a request and suits placeholders and CSS. A file or endpoint is needed when the request itself is the point, as with tracking pixels.
- Which Content-Type should I send?
image/gif. AddCache-Control: no-storeif every request must reach your server.