GIF to PNG Converter That Reads Every Frame

Most GIF to PNG converters hand a GIF to the browser, screenshot whatever it draws, and call the first frame the answer. This page parses the GIF bytes instead: header, palettes, disposal flags and the LZW pixel data. That is why frame 12 of an animation arrives looking like frame 12 rather than a small patch floating on an empty background.

GIF to PNG conversion workbench

Drop a GIF here, paste one, or tap to browse

GIF only, up to 50MB and 40 megapixels. Decoding happens in this tab.

What happens when you convert GIF to PNG

A GIF and a PNG store colour in different ways, so the conversion is never a straight copy. GIF keeps a palette of at most 256 colours and marks one palette slot as invisible. PNG stores full colour with a real alpha channel per pixel. Going from GIF to PNG widens the container without adding anything back, and the interesting decisions all sit in what happens to animation frames on the way through.

The first frame problem

Animated GIFs rarely store whole pictures. After frame one, a well compressed GIF writes only the rectangle that changed. A mouth moving in a 400 by 300 cartoon might be a 60 by 40 patch with an offset. Every frame carries a disposal flag saying what to do with the previous frame before drawing the next one.

A converter built on <img> and a canvas never sees any of that. The browser hands over one rendered still, and everything after it is out of reach. Converters that offer a frame slider on top of that model are moving a control connected to nothing. This page reads the file itself, replays the disposal rules in order, and stores each frame as a finished full size image. That is why the frame strip below the preview shows complete pictures instead of floating patches.

Disposal methods, and why frames look broken without them

FlagNameWhat the decoder doesSkipping it produces
0UnspecifiedLeave the canvas alone and draw the next patch over itUsually fine, since most encoders mean "keep"
1Do not disposeKeep every pixel already drawnNothing visible. This is the common case
2Restore to backgroundClear the frame rectangle to transparent before the next frameTrails and smearing, as old pixels never get erased
3Restore to previousRoll the canvas back to the state before this frameOverlays and flashes that stick around permanently

Flag 2 is where naive extraction falls apart most visibly. Text overlays and cursor animations lean on it heavily, and a decoder ignoring the flag turns a clean animation into a pile of stacked ghosts. The frame thumbnails on this page are the composited result, so what you see in the strip is what lands in the PNG.

Transparency crosses over, but it does not improve

GIF transparency is one bit. A palette index is either invisible or fully opaque, with nothing in between. PNG gives each pixel 256 levels of alpha. The conversion moves the invisible pixels across as alpha zero and everything else as alpha 255, which is correct and also the ceiling.

The practical result: jagged edges in the GIF stay jagged in the PNG. GIF encoders normally hide this by matting artwork against the background colour it will sit on, so a logo cut for a white page carries a faint white fringe baked into its edge pixels. Convert that to PNG, drop it on a dark panel, and the fringe shows. Nothing in a converter fixes it, because the softer edge was thrown away when the GIF was first written. Re-export from the original artwork when edge quality matters.

Expect the PNG to be larger than the GIF. The browser encoder writes 32-bit RGBA PNG with no palette, so a 256 colour image gets stored at four bytes per pixel before compression. A 40KB animated GIF often expands into 60KB of PNG per frame. Converting is about getting a lossless still into a pipeline, never about saving bytes. Run the results through an optimiser afterwards if size matters.

Sprite sheets, and when to pick one

The sheet mode tiles every decoded frame into a single PNG on a fixed grid, left to right and top to bottom. Each cell is the full logical size of the GIF, so cells line up exactly and a CSS background-position step or an engine spritesheet importer reads them without hand measuring. The column slider shows the finished pixel dimensions before you commit, which matters because a 40 frame GIF at one column produces a very tall texture that some GPUs refuse to sample.

Choose the sheet when the destination animates by shifting a viewport across one image: CSS steps animations, Unity or Godot sprite imports, or a shader sampling a flipbook. Choose the ZIP when frames are edited individually, fed to a video encoder, or reviewed one at a time. Choose a single frame when a still is all anyone wanted, which is most of the time a poster image is being pulled out of a screen recording.

Frame timing does not survive the trip

Each GIF frame carries its own delay, in hundredths of a second. The source panel reports the total loop length and each thumbnail shows its own hold time on hover, since uneven timing is common and worth knowing before rebuilding an animation elsewhere. PNG has nowhere to keep any of it. Once frames are exported, the pacing lives only in whatever you rebuild them with, and assuming a flat frame rate across the set will drift against the original.

Delays below 20ms are a related trap. Browsers historically clamp anything under that to 100ms, so a GIF claiming 10ms per frame plays far slower than its own header suggests. Rebuild against the real numbers rather than the playback you remember.

What the decoder reports, and why it helps

Limits worth knowing before relying on this

Everything runs in this tab. The GIF is read into memory as bytes, decoded in JavaScript on this page, and the PNG or ZIP is offered from browser memory. No request carries the image anywhere, which matters when the GIF is a screen recording of internal software.

GIF to PNG questions people actually hit

Frames, transparency, file size and the reasons an extracted frame sometimes looks wrong.

Why do other converters only give me the first frame?

Because they load the GIF into an image element and copy whatever the browser paints, which is a single still. The rest of the frames sit inside the file and never reach the canvas. This page parses the GIF structure directly, reads the LZW compressed pixel data for each frame, and rebuilds all of them, so the frame strip lists every frame the file contains.

My extracted frame is a small patch on an empty background. What went wrong?

That is a partial frame shown without compositing. Animated GIFs store only the rectangle that changed after frame one, so frame five might be a 60 by 40 patch with an offset. Each frame here is composited onto the running canvas using its disposal flag before export, so exported PNGs are full size and complete rather than isolated patches.

Does the PNG keep transparency from the GIF?

Yes, with the limit GIF imposes. GIF marks one palette index as fully invisible and has no partial transparency, so those pixels arrive in the PNG at alpha zero and everything else at alpha 255. Edges stay as hard as they were. If the GIF was matted against white, that white fringe is part of the pixels and comes across with them.

Why is my PNG bigger than the whole GIF?

The browser writes 32-bit RGBA PNG with no palette, so a 256 colour image is stored at four bytes per pixel before compression, while the GIF stored one byte per pixel plus a small colour table. Expect a single PNG frame to rival or beat the size of the entire animation. Run the output through an image optimiser if the file is heading to the web.

What is the sprite sheet mode for?

Animating by moving a viewport across one image instead of swapping files. CSS steps animations, Unity and Godot sprite importers, and flipbook shaders all read a grid like this. Every cell is the full logical size of the GIF so the grid stays even, and the column slider reports the finished dimensions before download, which catches textures that grow too tall to sample.

Can I get the animation back as a moving PNG?

Not from this page. Output is still images: one PNG, a ZIP of numbered PNGs, or a sprite sheet. APNG needs a different encoder, and browsers will not write one from a canvas. Take the ZIP into an APNG or WebP tool if the result has to move, and note the frame delays first, since PNG stores none of them.

How is the ZIP built if nothing is uploaded?

The ZIP is assembled in JavaScript on this page. Each frame is encoded to PNG bytes, given a CRC32 checksum and a local file header, and the central directory is written at the end. Entries are stored without compression, since PNG data is already compressed and a second pass would add time for almost no saving. The result is a normal ZIP that any archiver opens.

Why does the frame count differ from what my editor shows?

Two common reasons. Some editors merge frames that share identical pixels, reporting fewer than the file stores. Others count a damaged file up to a different point. Decoding here stops cleanly at the first malformed block, so a short count on a file you know is longer usually means the GIF was truncated in transit rather than misread.

Do the frame delays come across?

They are read and reported, and then lost. The source panel shows the total loop length, each thumbnail carries its hold time, and PNG has nowhere to store any of it. Write the timing down before you rebuild the animation somewhere else, since GIF frames often use uneven delays and treating them as a flat frame rate drifts against the original.

Is my GIF uploaded anywhere?

No. The file is read into browser memory as bytes, decoded on this page, and the download is created from that memory. Nothing leaves the tab after the page loads, which matters for screen recordings of internal tools or client work. Closing the tab discards the frames and the file.