— Design & Creative

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.

— Samples
Layers 2Problems 0Valid
Live

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.

1

Open the File

Choose a Lottie .json file or paste its JSON.

2

Play and Scrub

Pause and drag through frames to check every moment.

3

Read the Info

Confirm the size, frame rate and duration your app expects.

4

Run the Check

Fix expressions, linked images or missing assets before shipping.

Worked Examples

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.

REF_001A two-layer loop with markers

“{ "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 } } ] } ] } ] }”

REF_002The same loop, checked

“{ "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 } } ] } ] } ] }”

REF_003An export with an expression and a linked image

“{ "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 } ] }”

REF_004A loader with a precomp and an embedded image

“{"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":{}}]}”

REF_005A text layer with a web font

“{"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}}]}}}]}”

REF_006A 3D card flip with a camera

“{"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":{}}]}”

REF_007Missing in and out points

“{"v":"5.7.4","fr":30,"w":200,"h":200,"layers":[]}”

REF_008A trailing comma

“{"v":"5.7.4","fr":30,"ip":0,"op":60,"w":200,"h":200,"layers":[{"ty":4,"nm":"Dot",}]}”

REF_009A .lottie archive

“PK manifest.json animations/a.json”

REF_010An animation with no frames

“{"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":{}}]}”

Field Reference

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.

01 / V

v

The Bodymovin version that exported the file, such as 5.7.4.

“What does v record?”

02 / FR

fr

Frame rate in frames per second.

“What is fr for a 30 fps file?”

03 / IP

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?”

04 / W

w and h

Width and height of the composition in pixels.

“Which keys give the size?”

05 / NM

nm

The composition name from After Effects.

“Where does nm come from?”

06 / LAYERS

layers

The layers, top to bottom, each with a type number in ty.

“What does ty 4 mean?”

07 / ASSETS

assets

Precomps and images that layers refer to by refId.

“How does a layer find its asset?”

08 / FONTS

fonts

Fonts used by text layers, sometimes with a web address in fPath.

“Which layers need fonts?”

09 / MARKERS

markers

Named points in time, used to play segments.

“What does a marker’s tm hold?”

10 / DDD

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.

Tip 01

Lottie JSON

A single .json file, as Bodymovin exports it. Images are embedded or sit in a folder beside it.

Tip 02

dotLottie

A .lottie ZIP archive with one or more animations, images and a manifest.

Tip 03

Opening a .lottie

Rename it to .zip, unzip it, and open the JSON in the animations folder.

Tip 04

File Size

dotLottie is compressed, so it’s usually much smaller to ship.

Tip 05

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.

Tip 01

Linked Images

Exports without embedded images break as soon as the folder is separated from the JSON.

Tip 02

Unsupported Effects

Glows, blurs and many effects vanish in players. Use shapes instead.

Tip 03

Huge Files

Embedded high-resolution images inflate files. Compress images or use dotLottie.

Tip 04

Frame Rate Mismatch

Animating at 60 fps doubles the keyframes but rarely looks smoother in a small icon.

Tip 05

Text Without Fonts

Text layers fall back to another font unless the font ships with the app.

Tip 06

Expressions

Wiggle and loopOut may not run in a player. Convert them to keyframes before export.

Frequently Asked Questions