Free Lottie Previewer
Open or paste a Lottie JSON file to play it frame by frame, read its layers and markers, and find what won’t render.
What is a Lottie Previewer?
Lottie is the JSON animation format that After Effects exports through the Bodymovin plug-in, played by Airbnb’s open-source Lottie libraries on the web, iOS and Android. This previewer plays a Lottie file frame by frame and shows what is inside it.
It plays animations with lottie-web’s light build, which draws SVG and never runs the JavaScript expressions a file may contain. Linked images and web fonts are left out, so opening a file requests nothing. The info view lists size, frame rate, layers, precomps and markers, and the check finds what won’t render as designed.
Key Features
Frame-by-Frame Player
Play, pause and scrub to any frame to check timing and easing.
Composition Info
Size, frame rate, duration, layers by type, assets, fonts and markers.
Render Check
Expressions, linked images, web fonts, missing assets and layers the player can’t draw.
Safe to Open
Expressions aren’t run and nothing is fetched, so unknown files can’t do anything.
Up to 10 MB
Large exports with embedded images open without uploading.
Perfect for everyone
- Motion designers
- Front-end and app developers
- Anyone handed a Lottie file to ship
How to Use the Lottie Previewer
Open a .json file exported from After Effects or downloaded from LottieFiles, or paste its contents. The player, info and check all read the same file, so a fix in the JSON shows up in every view.
Open the File
Choose a Lottie .json file or paste its JSON.
Play and Scrub
Pause and drag through frames to check every moment.
Read the Info
Confirm the size, frame rate and duration your app expects.
Run the Check
Fix expressions, linked images or missing assets before shipping.
Lottie Files, Inspected
Each row is a Lottie file of the kind teams pass around, from a hand-written loop to an After Effects export with problems. Each answer is this tool’s info or check, read from the JSON without playing it, so the results don’t depend on a browser.
“{ "v": "5.7.4", "fr": 30, "ip": 0, "op": 60, "w": 200, "h": 200, "nm": "Pulse", "ddd": 0, "assets": [], "markers": [ { "tm": 0, "cm": "grow", "dr": 30 }, { "tm": 30, "cm": "shrink", "dr": 30 } ], "layers": [ { "ddd": 0, "ind": 1, "ty": 4, "nm": "Dot", "sr": 1, "ao": 0, "ip": 0, "op": 60, "st": 0, "bm": 0, "ks": { "o": { "a": 0, "k": 100 }, "r": { "a": 0, "k": 0 }, "p": { "a": 0, "k": [ 100, 100, 0 ] }, "a": { "a": 0, "k": [ 0, 0, 0 ] }, "s": { "a": 1, "k": [ { "t": 0, "s": [ 60, 60, 100 ], "i": { "x": [ 0.4 ], "y": [ 1 ] }, "o": { "x": [ 0.6 ], "y": [ 0 ] } }, { "t": 30, "s": [ 100, 100, 100 ], "i": { "x": [ 0.4 ], "y": [ 1 ] }, "o": { "x": [ 0.6 ], "y": [ 0 ] } }, { "t": 60, "s": [ 60, 60, 100 ] } ] } }, "shapes": [ { "ty": "gr", "nm": "Circle", "it": [ { "ty": "el", "nm": "Ellipse", "d": 1, "p": { "a": 0, "k": [ 0, 0 ] }, "s": { "a": 0, "k": [ 90, 90 ] } }, { "ty": "fl", "nm": "Fill", "c": { "a": 0, "k": [ 0.95, 0.42, 0.2, 1 ] }, "o": { "a": 0, "k": 100 }, "r": 1 }, { "ty": "tr", "p": { "a": 0, "k": [ 0, 0 ] }, "a": { "a": 0, "k": [ 0, 0 ] }, "s": { "a": 0, "k": [ 100, 100 ] }, "r": { "a": 0, "k": 0 }, "o": { "a": 0, "k": 100 } } ] } ] }, { "ddd": 0, "ind": 2, "ty": 4, "nm": "Frame", "sr": 1, "ao": 0, "ip": 0, "op": 60, "st": 0, "bm": 0, "ks": { "o": { "a": 0, "k": 100 }, "r": { "a": 1, "k": [ { "t": 0, "s": [ 0 ], "i": { "x": [ 0.4 ], "y": [ 1 ] }, "o": { "x": [ 0.6 ], "y": [ 0 ] } }, { "t": 60, "s": [ 90 ] } ] }, "p": { "a": 0, "k": [ 100, 100, 0 ] }, "a": { "a": 0, "k": [ 0, 0, 0 ] }, "s": { "a": 0, "k": [ 100, 100, 100 ] } }, "shapes": [ { "ty": "gr", "nm": "Square", "it": [ { "ty": "rc", "nm": "Rectangle", "d": 1, "p": { "a": 0, "k": [ 0, 0 ] }, "s": { "a": 0, "k": [ 150, 150 ] }, "r": { "a": 0, "k": 12 } }, { "ty": "st", "nm": "Stroke", "c": { "a": 0, "k": [ 0.1, 0.1, 0.1, 1 ] }, "o": { "a": 0, "k": 100 }, "w": { "a": 0, "k": 6 }, "lc": 2, "lj": 2 }, { "ty": "tr", "p": { "a": 0, "k": [ 0, 0 ] }, "a": { "a": 0, "k": [ 0, 0 ] }, "s": { "a": 0, "k": [ 100, 100 ] }, "r": { "a": 0, "k": 0 }, "o": { "a": 0, "k": 100 } } ] } ] } ] }”
“{ "v": "5.7.4", "fr": 30, "ip": 0, "op": 60, "w": 200, "h": 200, "nm": "Pulse", "ddd": 0, "assets": [], "markers": [ { "tm": 0, "cm": "grow", "dr": 30 }, { "tm": 30, "cm": "shrink", "dr": 30 } ], "layers": [ { "ddd": 0, "ind": 1, "ty": 4, "nm": "Dot", "sr": 1, "ao": 0, "ip": 0, "op": 60, "st": 0, "bm": 0, "ks": { "o": { "a": 0, "k": 100 }, "r": { "a": 0, "k": 0 }, "p": { "a": 0, "k": [ 100, 100, 0 ] }, "a": { "a": 0, "k": [ 0, 0, 0 ] }, "s": { "a": 1, "k": [ { "t": 0, "s": [ 60, 60, 100 ], "i": { "x": [ 0.4 ], "y": [ 1 ] }, "o": { "x": [ 0.6 ], "y": [ 0 ] } }, { "t": 30, "s": [ 100, 100, 100 ], "i": { "x": [ 0.4 ], "y": [ 1 ] }, "o": { "x": [ 0.6 ], "y": [ 0 ] } }, { "t": 60, "s": [ 60, 60, 100 ] } ] } }, "shapes": [ { "ty": "gr", "nm": "Circle", "it": [ { "ty": "el", "nm": "Ellipse", "d": 1, "p": { "a": 0, "k": [ 0, 0 ] }, "s": { "a": 0, "k": [ 90, 90 ] } }, { "ty": "fl", "nm": "Fill", "c": { "a": 0, "k": [ 0.95, 0.42, 0.2, 1 ] }, "o": { "a": 0, "k": 100 }, "r": 1 }, { "ty": "tr", "p": { "a": 0, "k": [ 0, 0 ] }, "a": { "a": 0, "k": [ 0, 0 ] }, "s": { "a": 0, "k": [ 100, 100 ] }, "r": { "a": 0, "k": 0 }, "o": { "a": 0, "k": 100 } } ] } ] }, { "ddd": 0, "ind": 2, "ty": 4, "nm": "Frame", "sr": 1, "ao": 0, "ip": 0, "op": 60, "st": 0, "bm": 0, "ks": { "o": { "a": 0, "k": 100 }, "r": { "a": 1, "k": [ { "t": 0, "s": [ 0 ], "i": { "x": [ 0.4 ], "y": [ 1 ] }, "o": { "x": [ 0.6 ], "y": [ 0 ] } }, { "t": 60, "s": [ 90 ] } ] }, "p": { "a": 0, "k": [ 100, 100, 0 ] }, "a": { "a": 0, "k": [ 0, 0, 0 ] }, "s": { "a": 0, "k": [ 100, 100, 100 ] } }, "shapes": [ { "ty": "gr", "nm": "Square", "it": [ { "ty": "rc", "nm": "Rectangle", "d": 1, "p": { "a": 0, "k": [ 0, 0 ] }, "s": { "a": 0, "k": [ 150, 150 ] }, "r": { "a": 0, "k": 12 } }, { "ty": "st", "nm": "Stroke", "c": { "a": 0, "k": [ 0.1, 0.1, 0.1, 1 ] }, "o": { "a": 0, "k": 100 }, "w": { "a": 0, "k": 6 }, "lc": 2, "lj": 2 }, { "ty": "tr", "p": { "a": 0, "k": [ 0, 0 ] }, "a": { "a": 0, "k": [ 0, 0 ] }, "s": { "a": 0, "k": [ 100, 100 ] }, "r": { "a": 0, "k": 0 }, "o": { "a": 0, "k": 100 } } ] } ] } ] }”
“{ "v": "5.12.1", "fr": 24, "ip": 0, "op": 48, "w": 512, "h": 512, "nm": "Badge", "assets": [ { "id": "image_0", "w": 512, "h": 512, "u": "images/", "p": "badge.png", "e": 0 } ], "layers": [ { "ind": 1, "ty": 2, "nm": "Badge art", "refId": "image_0", "ip": 0, "op": 48, "st": 0, "ks": { "o": { "a": 0, "k": 100 }, "r": { "a": 1, "k": 0, "x": "time * 45" }, "p": { "a": 0, "k": [ 256, 256, 0 ] }, "a": { "a": 0, "k": [ 256, 256, 0 ] }, "s": { "a": 0, "k": [ 100, 100, 100 ] } } }, { "ind": 2, "ty": 0, "nm": "Sparkles", "refId": "comp_3", "w": 512, "h": 512, "ip": 0, "op": 48, "st": 0, "ks": { "o": { "a": 0, "k": 100 }, "r": { "a": 0, "k": 0 }, "p": { "a": 0, "k": [ 256, 256, 0 ] }, "a": { "a": 0, "k": [ 256, 256, 0 ] }, "s": { "a": 0, "k": [ 100, 100, 100 ] } } }, { "ind": 3, "ty": 6, "nm": "Chime", "ip": 0, "op": 48, "st": 0 } ] }”
“{"v":"5.10.2","fr":60,"ip":0,"op":120,"w":1080,"h":1080,"nm":"Loader","assets":[{"id":"comp_0","nm":"Spinner","layers":[{"ind":1,"ty":4,"nm":"Arc","ip":0,"op":120,"st":0,"ks":{},"shapes":[]}]},{"id":"image_0","w":64,"h":64,"u":"","p":"data:image/png;base64,iVBORw0KGgo=","e":1}],"layers":[{"ind":1,"ty":0,"nm":"Spinner","refId":"comp_0","w":1080,"h":1080,"ip":0,"op":120,"st":0,"ks":{}},{"ind":2,"ty":2,"nm":"Logo","refId":"image_0","ip":0,"op":120,"st":0,"ks":{}},{"ind":3,"ty":3,"nm":"Controller","ip":0,"op":120,"st":0,"ks":{}}]}”
“{"v":"5.9.0","fr":30,"ip":0,"op":90,"w":800,"h":200,"nm":"Headline","fonts":{"list":[{"fName":"Inter-Bold","fFamily":"Inter","fStyle":"Bold","fPath":"https://fonts.googleapis.com/css2?family=Inter:wght@700","origin":1}]},"layers":[{"ind":1,"ty":5,"nm":"Title","ip":0,"op":90,"st":0,"ks":{},"t":{"d":{"k":[{"t":0,"s":{"t":"Launch day","f":"Inter-Bold","s":72}}]}}}]}”
“{"v":"5.7.4","fr":25,"ip":0,"op":50,"w":400,"h":400,"nm":"Card flip","ddd":1,"layers":[{"ind":1,"ty":13,"nm":"Camera 1","ip":0,"op":50,"st":0},{"ind":2,"ty":1,"nm":"Card","ddd":1,"sc":"#2f6fed","sw":300,"sh":200,"ip":0,"op":50,"st":0,"ks":{}}]}”
“{"v":"5.7.4","fr":30,"w":200,"h":200,"layers":[]}”
“{"v":"5.7.4","fr":30,"ip":0,"op":60,"w":200,"h":200,"layers":[{"ty":4,"nm":"Dot",}]}”
“PK manifest.json animations/a.json”
“{"v":"5.7.4","fr":30,"ip":0,"op":0,"w":200,"h":200,"nm":"Still","layers":[{"ind":1,"ty":1,"nm":"Background","sc":"#ffffff","sw":200,"sh":200,"ip":0,"op":0,"st":0,"ks":{}}]}”
Top-Level Lottie Fields
Lottie uses short keys to keep files small, which makes the JSON hard to read at first. These are the fields at the top of every animation, the ones the info view reads, and what each one controls.
v
The Bodymovin version that exported the file, such as 5.7.4.
“What does v record?”
fr
Frame rate in frames per second.
“What is fr for a 30 fps file?”
ip and op
In and out points: the first frame and the frame after the last.
“How many frames run from ip 0 to op 60?”
w and h
Width and height of the composition in pixels.
“Which keys give the size?”
nm
The composition name from After Effects.
“Where does nm come from?”
layers
The layers, top to bottom, each with a type number in ty.
“What does ty 4 mean?”
assets
Precomps and images that layers refer to by refId.
“How does a layer find its asset?”
fonts
Fonts used by text layers, sometimes with a web address in fPath.
“Which layers need fonts?”
markers
Named points in time, used to play segments.
“What does a marker’s tm hold?”
ddd
1 when the composition uses 3D layers.
“What does ddd 1 mean?”
What Lottie Players Support
Lottie players re-create After Effects features in code, and none of them supports everything After Effects can do. Knowing the gaps helps you design animations that look the same on every platform, rather than finding out after the app ships.
Shapes and Masks
Shape layers, fills, strokes, trims and masks are supported by every player.
Expressions
Only some players run them, and only a subset. Bake expressions into keyframes for reliability.
Effects
Most After Effects effects are ignored. A few, like fill and tint, are supported on some platforms.
3D Layers
Support is partial and differs between web, iOS and Android.
Text
Text layers need their fonts available, or can be converted to shapes before export.
Images
Embed images as Base64 so the file plays without a separate images folder.
Lottie JSON and dotLottie
Lottie animations travel in two forms. Both play in the same players, but they package the animation differently, and this previewer opens the JSON form, which is the one inside every dotLottie archive.
Lottie JSON
A single .json file, as Bodymovin exports it. Images are embedded or sit in a folder beside it.
dotLottie
A .lottie ZIP archive with one or more animations, images and a manifest.
Opening a .lottie
Rename it to .zip, unzip it, and open the JSON in the animations folder.
File Size
dotLottie is compressed, so it’s usually much smaller to ship.
Specification
The Lottie Animation Community, part of the Linux Foundation, maintains an open spec.
When to Use a Lottie Previewer
Whenever a Lottie file changes hands between design and development, and someone needs to see it play and confirm what it contains before it goes into a product.
Design Handoff
Check an export plays as designed before handing it to developers.
Code Review
Confirm a new animation’s size and frame rate in a pull request.
Debugging
Find why an animation is blank or frozen in an app.
Choosing Files
Inspect a downloaded animation before adding it to a product.
Timing Checks
Scrub to marker frames to set up segment playback.
Lottie Pitfalls
Problems that show up only after an animation leaves After Effects, usually because a player handles a feature differently from the editor or a file was exported with the wrong settings.
Linked Images
Exports without embedded images break as soon as the folder is separated from the JSON.
Unsupported Effects
Glows, blurs and many effects vanish in players. Use shapes instead.
Huge Files
Embedded high-resolution images inflate files. Compress images or use dotLottie.
Frame Rate Mismatch
Animating at 60 fps doubles the keyframes but rarely looks smoother in a small icon.
Text Without Fonts
Text layers fall back to another font unless the font ships with the app.
Expressions
Wiggle and loopOut may not run in a player. Convert them to keyframes before export.