Why Lottie Files Are Trapped in Apps
A Lottie file is a JSON description of vector animation. Designers in After Effects use the Bodymovin plugin to export their animations as Lottie. Mobile apps and web pages render those JSON files using the Lottie runtime library. The animation stays vector-sharp at any resolution, file sizes are tiny (often under 50 KB), and motion is perfectly smooth.
The problem: outside of apps that ship the Lottie runtime, nothing plays Lottie files. Email clients can't render them. Slack messages don't recognize them. LinkedIn posts ignore them. PowerPoint won't import them.
To share a Lottie animation with anyone outside an app context, you have to render it to a video format. MP4 for high-quality playback. GIF for universal compatibility (especially in email and Slack). Our GIF maker handles the GIF side once you have a video source.
This post covers rendering Lottie to MP4 and GIF, the trade-offs of each, and the pitfalls that produce stuttery or pixelated output.
What Lottie Is, Briefly
A Lottie file is JSON. Open one in a text editor and you'll see:
{
"v": "5.7.4",
"fr": 30,
"ip": 0,
"op": 90,
"w": 400,
"h": 400,
"nm": "Comp 1",
"layers": [...]
}
Key fields:
fris frame rate (30 fps)ipis in-point (start frame)opis out-point (end frame, exclusive)wandhare dimensions in pixelslayerscontains the actual animation data
The layers describe vector shapes, masks, transformations, and animation curves. The Lottie runtime interprets this at playback time. The output is dynamic, not pre-rendered.
This is why Lottie files are so small (no pixel data) and so flexible (resolution-independent). The trade-off: you need a Lottie runtime to play them.
Rendering Lottie to MP4
The cleanest path is to render through a headless browser running the Lottie web runtime, capturing each frame as a PNG, then encoding to MP4.
For one-off conversions, our JSON to MP4 converter accepts Lottie files directly.
For programmatic conversion using Puppeteer:
const puppeteer = require("puppeteer");
const lottie = require("lottie-web");
async function lottieToFrames(jsonPath, outputDir) {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setViewport({ width: 800, height: 800 });
const html = `
<!DOCTYPE html>
<html><body style="margin:0">
<div id="anim" style="width:800px;height:800px"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bodymovin/5.10.2/lottie.min.js"></script>
<script>
const animationData = ${JSON.stringify(require(jsonPath))};
const anim = lottie.loadAnimation({
container: document.getElementById('anim'),
renderer: 'svg',
loop: false,
autoplay: false,
animationData: animationData
});
window.totalFrames = animationData.op - animationData.ip;
</script>
</body></html>
`;
await page.setContent(html);
await page.waitForFunction("window.totalFrames !== undefined");
const totalFrames = await page.evaluate("window.totalFrames");
for (let i = 0; i < totalFrames; i++) {
await page.evaluate(`anim.goToAndStop(${i}, true)`);
await page.screenshot({
path: `${outputDir}/frame_${String(i).padStart(4, "0")}.png`,
omitBackground: true,
});
}
await browser.close();
}
Then encode to MP4 with FFmpeg:
ffmpeg -framerate 30 -i frame_%04d.png \
-c:v libx264 -preset slow -crf 18 \
-pix_fmt yuv420p \
-movflags +faststart \
output.mp4
CRF 18 is visually lossless. Drop to CRF 24 for smaller files at acceptable quality.
Rendering Lottie to GIF
GIF is the universal-but-mediocre option. It plays in email, Slack, LinkedIn, and Twitter, but caps at 256 colors per frame and produces files 5-10x larger than equivalent MP4.
The cleanest GIF path: render Lottie to MP4 first (steps above), then convert MP4 to GIF:
ffmpeg -i input.mp4 \
-vf "fps=15,scale=480:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" \
-loop 0 \
output.gif
The two-pass palette generation produces dramatically better quality than the single-pass default. Without it, GIFs look posterized.
Our MP4 to GIF converter automates this pipeline. For Lottie files specifically, GIF maker accepts the MP4 intermediate.
| GIF setting | File size | Quality |
|---|---|---|
| 30 fps, 800x800 | 8-15 MB | Smooth but huge |
| 15 fps, 480x480 | 1-3 MB | Good for Slack |
| 12 fps, 320x320 | 400-800 KB | Email-friendly |
| 8 fps, 240x240 | 150-300 KB | Tweet-friendly |
For most Slack and email use: 15 fps, 480px width, 1-3 MB final size. That's the sweet spot.
Pro Tip: Slack's file size limit for inline GIF previews is 8 MB on free workspaces. Above that, the GIF uploads as a file attachment and doesn't auto-play. Stay under 5 MB to be safe.
Background Transparency
Lottie animations often have transparent backgrounds (especially loaders and UI animations). MP4 can't carry transparency. GIF can but only as 1-bit alpha (fully transparent or fully opaque, no partial transparency).
For transparent output, your real options are:
- WebM with VP9 alpha: full alpha channel, plays in modern browsers
- APNG: Animated PNG with full alpha, plays in browsers and some apps
- HEVC alpha (Apple-specific): works on Apple platforms only
# WebM with alpha
ffmpeg -framerate 30 -i frame_%04d.png \
-c:v libvpx-vp9 -pix_fmt yuva420p \
-auto-alt-ref 0 \
output.webm
# APNG
ffmpeg -framerate 30 -i frame_%04d.png \
-plays 0 \
output.png
For Slack messages: APNG works in newer Slack versions. WebM works in browsers but not Slack's mobile apps.
When to Use Which Format
| Destination | Best format | Fallback |
|---|---|---|
| GIF (small) | Static PNG of first frame | |
| Slack desktop | APNG or GIF | WebM |
| Slack mobile | GIF | Static |
| LinkedIn post | MP4 | GIF |
| Twitter/X | MP4 | GIF |
| Instagram Story | MP4 | n/a |
| PowerPoint | MP4 | GIF |
| Keynote | MP4 | GIF |
| Notion page | MP4 | GIF |
| Figma comment | GIF | Static |
For mixed-platform sharing, MP4 + GIF as a backup covers nearly everything.
Converting Lottie Files at Scale
Common production scenarios:
Marketing site library: 50 Lottie files, all need MP4 + GIF for marketing email. Use the Puppeteer pipeline above wrapped in a folder loop.
Product onboarding: 12 Lottie loaders, all need MP4 for video walkthrough. Render at 1080×1080 for high-quality web playback.
Slack emoji set: 30 Lottie files, all need GIF under 1 MB. Render at 256×256, 12 fps.
For batch processing, see Batch Processing Files Guide. The same patterns apply.
Quality Settings That Matter
Three things produce stuttery or pixelated output from Lottie conversions:
Frame rate mismatch: The Lottie's fr field is the source frame rate. Render at the same rate. Down-sampling to 15 fps for a 30 fps Lottie causes motion stutter unless you're going to GIF (where 15 fps is the standard).
Resolution mismatch: Lottie is vector. Render at any resolution, but pick a multiple of the original. 2x the source dimensions is the typical "high quality" setting. 4x is overkill for most cases.
Anti-aliasing: SVG renderer in the Lottie runtime produces clean vector edges. Canvas renderer is faster but slightly more pixelated. Use SVG renderer for output rendering, even though it's slower.
Lottie File Optimization Before Render
Some Lottie files contain features that don't render well to video:
- Expressions (JavaScript-evaluated property values): may not work in non-JS Lottie runtimes
- Image layers (raster images embedded in JSON): need to be present at render time
- Text layers: font availability matters
- Mattes and complex masks: render correctly but slowly
If your Lottie file is large (over 200 KB), it likely contains image layers. Verify those images are accessible during rendering. The Bodymovin export with "include images" produces a self-contained JSON. Without that flag, image paths are relative.
Frequently Asked Questions
Why does my Lottie GIF look choppy?
Frame rate too low for the source motion. Lottie runs at 30 or 60 fps natively. GIF at 15 fps looks fine for most UI animation but choppy for character movement. Increase to 24 fps and accept the file size hit.
Can I render Lottie to MP4 in After Effects?
Yes. Open the original AE project (the one Bodymovin came from), render with the standard Render Queue. You don't need to export to Lottie and back. If you only have the Lottie JSON and not the AE source, use the Puppeteer pipeline above.
How do I keep transparency in MP4?
You can't. MP4 doesn't support alpha channels. For transparent video output, use WebM with VP9 alpha or APNG. For most app use cases, transparency comes from the rendering platform (Lottie runtime), not the file format.
Why is my converted MP4 so much bigger than the JSON?
JSON is vector instructions, MP4 is pixel data. A 50 KB Lottie can render to a 5 MB MP4 at 1080p. That's expected. Vector-to-raster conversion always increases file size dramatically.
Can I convert MP4 back to Lottie?
No. MP4 to Lottie would require AI motion vectorization, which doesn't exist as a reliable tool. Lottie is forward-only from After Effects.
What's the smallest GIF I can make from Lottie?
256x256 at 8 fps, 64 colors, with frame skipping for low-motion sections. Around 120-180 KB for a 3-second loop. See our GIF maker for the conversion controls.
Related Reading
Bottom Line
For Lottie files destined for outside-app use: render to MP4 for high-quality playback (LinkedIn, Twitter, Notion, PowerPoint), GIF for universal compatibility (email, Slack, older platforms). Use Puppeteer + FFmpeg for programmatic rendering, or our GIF maker and MP4 converter for one-off conversions. Keep transparency by going to WebM or APNG instead.


