Sprite Animation Previewer
Play a sprite sheet back at any frame rate, check the loop, and export it as an animated GIF — before you find out in the engine that frame 7 is a pixel off. Free, no sign-up, and every pixel stays in your browser.
Nothing is uploaded — the animation is decoded and played inside your browser.
How to preview a sprite animation
Four steps from a static sheet to a loop you trust.
- 1Load a sheet or a set of framesOne file is cut into a grid — guessed from the artwork on load. Several files are played in numeric name order, so
frame_2comes beforeframe_10. Drop an Aseprite.jsonalongside the sheet and the frames, their tags and their timings all come from the file. - 2Fix the grid if the guess missedCorrect the columns and rows, add offset and spacing for a padded sheet, or switch to auto-detect for a packed atlas. Empty cells are skipped by default. With a JSON imported there is nothing to fix — the file already says where every frame is.
- 3Find the right frame rate and rangeSlide the frame rate until the motion reads properly, then narrow the range to isolate one animation from a sheet holding several. An imported tag does both at once.
- 4ExportSave the loop as an animated GIF at 1× to 8×, or pull the current frame out as a PNG.
What you are actually checking
A sprite sheet tells you nothing about timing, and timing is most of what makes an animation work. Frames that look fine side by side can read as a stutter at 12 fps and as mush at 24. The only way to know is to watch it.
Three problems show up immediately in playback and almost never in a static sheet. A loop seam: the last frame is too close to the first, so the cycle hitches once per revolution. A registration error: one frame is drawn a pixel off-centre, and the sprite twitches every time it comes round. And uneven spacing: two frames doing the work of one, so the motion accelerates halfway through.
Stepping frame by frame with the arrow buttons is the fastest way to find the second one. Narrowing the range to two or three frames and letting it loop is the fastest way to find the other two.
Playing an Aseprite export with its own timing
A frame rate is an average. Aseprite stores a duration per frame, and the difference is visible.
In Aseprite, File → Export Sprite Sheet with JSON Data ticked on the Output tab. Drop the PNG and the .json in together and three things change.
The frames come from the file, not from a grid you worked out or a detection pass that had to guess. Different frame sizes, irregular spacing and trimmed exports stop mattering.
Timing is per frame. This is the part a single frame-rate slider cannot express. A walk cycle usually holds the two contact frames — where the foot lands and takes the weight — longer than the passing frames between them, and animators do that on purpose. Played at a flat 12 fps the whole thing reads as mechanical. Each frame's hold is shown under its thumbnail in the timeline, so you can see which ones were given the extra time.
Tags become an animation picker. Selecting one sets the range and the direction together, so a ping-pong tag plays as a ping-pong and a reverse tag plays backwards without you finding the loop control. Nothing has to be counted out of a sheet holding idle, walk, attack and hurt end to end.
The GIF export uses the same timings, so what downloads matches what you watched. One caveat the format imposes: GIF stores delays in hundredths of a second, so a 100ms Aseprite frame is exact while 33ms is written as 30 — a rounding you will not see, but which is there.
TexturePacker JSON works too. It carries the frame rectangles but no durations or tags, so you get the accurate cut and keep the frame-rate slider.
Frame rates that suit pixel animation
Most hand-drawn pixel animation lives between 8 and 15 fps. That is not a technical limit — it is a drawing budget. Every frame is a frame somebody has to draw, and beyond about 15 the extra ones stop adding readable information and start adding work.
Fast actions are the exception: an attack or a dash often runs at 20 to 24 fps for the few frames it lasts, because the motion is meant to feel abrupt. Idles go the other way, sometimes as low as 4 to 6 fps.
Whatever you choose, note it down — the engine needs the same number. A cycle authored at 12 fps and played at 10 in Godot will look subtly wrong and you will blame the art.
About the GIF export
The GIF is encoded here, in the page, with no upload and no service in between. Two properties of the format are worth knowing before you rely on it.
Timing is quantised to 10ms. GIF stores each frame's delay in hundredths of a second, so 10 fps (10cs) and 20 fps (5cs) come out exact, while 12 fps rounds to 8cs — 12.5 fps in a player. The tool shows the rounded rate. The format also cannot go faster than 50 fps, and many viewers silently floor anything under 2cs.
Transparency is one bit. A pixel is either fully transparent or fully opaque; there is no partial alpha. Pixel art almost never uses partial alpha, so this rarely matters — but a sprite with a soft glow or an anti-aliased edge will show a hard boundary in the GIF that the PNG did not have.
The palette holds 255 colours plus transparency. Pixel art usually uses a few dozen and comes through exactly; anything with gradients gets quantised down.
When you need this
Checking a sheet you just cut
Pull a sheet apart with the Sprite Sheet Cutter, then play it here to confirm the grid landed on the right pixel before importing anything.
Evaluating an asset pack
A marketplace preview image tells you what the frames look like, not how they move. Play the sheet before you build a character around it.
Sharing work in progress
A GIF plays in Discord, in an issue tracker and on a store page. A sprite sheet does not.
Isolating one animation
Sheets often hold idle, walk and attack in separate rows. Narrow the range to one row and check each in turn.
Frequently asked questions
How do I preview a sprite sheet animation?
Drop the sheet in. The grid is guessed from the artwork, the frames start playing immediately, and you can correct the columns and rows if the guess was wrong. Set the frame rate, pick a range, and watch the loop before you commit it to an engine.
Can it play an Aseprite export with the original frame timing?
Yes. Export from Aseprite with JSON Data on the Output tab, then drop the PNG and the .json in together. Each frame is held for the duration Aseprite recorded rather than an averaged frame rate, which matters because animators deliberately hold some frames longer than others — a walk cycle usually holds its contact frames. The hold length is shown under each timeline thumbnail, frame tags become an animation picker that sets the range and direction together, and the GIF export uses the same timings.
Can I convert a sprite sheet to an animated GIF?
Yes. Set the frame rate and range you want, choose a scale, and export. The GIF loops forever, keeps the sheet's transparency, and is encoded in your browser — the file is never uploaded anywhere.
Why does my exported GIF play at a slightly different speed?
GIF stores frame delays in hundredths of a second, so it cannot express every frame rate exactly. 10 fps is exactly 10cs and comes out right; 12 fps rounds to 8cs, which is 12.5 fps. The tool shows the rounded rate next to the export button. GIF also cannot go faster than 50 fps.
Can I preview individual frames instead of a sheet?
Yes — select all of them at once. They are ordered numerically by file name, so frame_2 plays before frame_10 even without zero padding. Drop a single file and it is treated as a sheet instead.
What frame rate should a sprite animation run at?
Hand-drawn pixel animation usually sits between 8 and 15 fps — enough to read as motion, few enough frames to actually draw. Fast actions like attacks often run at 20 to 24. Higher than that and you are drawing frames nobody will see.
What is ping-pong looping?
The animation plays to the end and then back to the start rather than jumping. It suits idle breathing, floating platforms and anything symmetrical, and it halves the number of frames you have to draw. It is wrong for a walk cycle, which needs to loop cleanly forwards.
Are my files uploaded to a server?
No. The sheet is decoded, cut, played and encoded to GIF entirely with browser APIs. Nothing leaves your machine, and the tool keeps working offline once the page has loaded.
Related guides
How to Turn a Sprite Sheet into a GIF
Grid, per-frame timing, transparency — and the limits of the format before you commit to it.
How to Import a Sprite Sheet into Godot
Slice it with AnimatedSprite2D, kill the blur, and know when Godot's slicer gives up.
How to Import a Sprite Sheet into Unity
Sprite Mode, the Sprite Editor's three slice modes, and the import settings that quietly ruin pixel art.
How to Load a Sprite Sheet in Phaser
spritesheet vs atlas, frameWidth in pixels, generateFrameNumbers — and why nothing loads over file://.
How to Fix Sprite Sheet Frames That Cut in the Wrong Place
Compare the first frame with the last. Whether the error grows tells you which of four things is wrong.
Related tools
Sprite Sheet Cutter
LiveSplit a sprite sheet into individual PNG frames by grid, auto-detection or an Aseprite JSON, then download them as a ZIP.
Sprite Sheet Generator
LivePack individual frames into one sprite sheet atlas, with a TexturePacker JSON manifest.
Pixel Art Resizer
LiveScale pixel art 2x / 4x / custom with nearest-neighbour — no blurring.
Pixel Art Palette Converter
LiveRead an image's palette, reduce it to a fixed colour count, or remap the art onto a console palette — then export it.
Browse everything on the game asset tools page.