Why your Lottie file is 70 MB

Lottie is a JSON format. You'd expect a JSON file describing an animation to be a few kilobytes at most. And for pure vector animations, it is. But the moment your designer's After Effects composition includes raster effects, the file can balloon to tens of megabytes. This article explains the structural reason, with concrete measurements, and what actually compresses it.

The structure of a Lottie file

A Lottie JSON has three top-level sections that matter for size: the animation header (canvas dimensions w, h, frame rate fr, in/out points ip/op), the layers array describing what to draw on each frame, and the assets array containing referenced sub-compositions and embedded image resources.

For a pure vector animation — say, a checkmark, a loading spinner, or a logo morph — the entire file is shape data: anchor points, bezier handles, color stops, and transform matrices. These are remarkably compact. A complex hand-drawn logo morph is typically under 30 KB.

The pivot point comes when a designer needs to express something vectors can't easily describe: soft glows, particle systems, fluid dynamics, photographic textures, or anything involving real image processing. In After Effects, these are routinely done with bitmap layers, sub-comps containing video, or precomposed effect stacks. None of them are representable as native Lottie shapes.

Enter Bodymovin and the PNG sequence escape hatch

Bodymovin, the After Effects plugin that exports Lottie JSON, has a clever fallback for the non-vector case: it renders the un-translatable layers to a sequence of PNG frames and inlines each frame into the JSON as a base64-encoded data URL. The result is a single self-contained animation file at the cost of dramatic size inflation.

Here's a typical assets entry:

{
  "id": "image_0",
  "p": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...",
  "e": 1,
  "u": ""
}

The p field carries the entire PNG, encoded as base64. Base64 itself adds about 33% overhead on top of the binary payload, so a 200 KB PNG becomes a ~270 KB string in the JSON. Multiply that by 150 frames in a 5-second animation at 30 fps, and you have a 40 MB JSON document — before any of the actual animation logic is even counted.

Real-world measurements

We've inspected several hundred reader-submitted Lottie files and the breakdown is remarkably consistent:

  • Vector-only files: 5 KB – 200 KB. Often shippable without further processing.
  • Mixed-content files with light raster effects: 1 MB – 8 MB. Still problematic on mobile.
  • Image-sequence-heavy files: 20 MB – 100 MB. Cannot ship without intervention.

The Inspector tool on this site classifies a file in two clicks: it walks the assets array, identifies entries whose p field is a data URL, and reports both the byte share and the per-asset breakdown. A 70 MB file might have 99% of its bytes locked up in fewer than a dozen image_* assets.

What doesn't compress well

It's worth understanding why ordinary tools fail on this problem.

Vector-only Lottie optimizers (the kind LottieFiles publishes, or the optimization flags in lottie-web's build pipeline) walk the shape tree and prune redundant keyframes, round floating-point coordinates, and dedupe identical layers. They are excellent for purely vector animations but never touch the assets array. A 70 MB file with embedded PNGs is still 70 MB after running through these tools.

Generic JSON minifiers remove whitespace, which is essentially free here: Bodymovin output is already minified. A few additional percent off the structural fields makes no measurable difference when 99% of the file is base64 image data.

Gzip and Brotli at the HTTP layer reduce the JSON by some amount, but base64-encoded PNG is essentially incompressible: PNG already does its own entropy coding internally, and wrapping it in base64 randomizes the byte distribution. Real-world Brotli on these files achieves 5–15% reduction at most, far short of what's needed.

What does compress: re-encoding to WebP

The leverage point is the embedded raster. Modern image formats reach quality parity with PNG at a fraction of the byte cost. WebP, in particular, at quality 75 typically produces files about 80% smaller than the equivalent PNG, with no perceptible visual difference for animation frames.

The lottie-mini compressor decodes each embedded PNG in your browser, re-encodes it as WebP via a WebAssembly build of libwebp, and rewrites the data URL in place. The output is still a single self-contained Lottie file that any modern player can consume.

And the second lever: frame skipping

Most animations that ship at 60 fps are imperceptible from 30 fps when re-encoded properly. Many ship comfortably at 24 fps or even 15 fps for slow-changing scenes. Dropping every other frame and adjusting the ip/op values to match cuts the asset payload by 50% with no perceived quality loss.

This is the second knob the compressor exposes. Combined with WebP re-encoding, a 70 MB Lottie often lands well under 1 MB — small enough to embed in a small-payload context like a WeChat Mini Program (2 MB total budget) or a mobile first-frame HTML payload.

The dotLottie wrinkle

The newer .lottie file format is a zip container holding the JSON plus images as separate files. This avoids base64 overhead by storing each PNG as a binary entry. dotLottie is meaningfully smaller than equivalent inlined JSON, but the embedded PNGs themselves are still PNGs — there's no automatic re-encoding to a better format.

The Inspector and Compressor both treat .lottie files as first-class input: they unzip in your browser using fflate, operate on the inner animation JSON, and re-zip the result, preserving the manifest and any sibling files.

When to stop optimizing and use video instead

There's a threshold beyond which Lottie stops being the right tool. If your animation is essentially a video — every frame is a fully different rendered scene with no shared geometry — then a short MP4 or WebM with the same frame rate will be smaller than any Lottie equivalent, and players like HTML5 video are battle-hardened. Lottie's advantages (interactivity, dynamic colors, sharp on any DPI, easy programmatic control) all evaporate when the content is just pixels.

A useful rule of thumb: if your compressed Lottie is still larger than 2 MB and is over 2 seconds long, check whether an H.264 MP4 of the same animation would be smaller. If yes, ship the MP4.

Summary

Lottie files explode in size because Bodymovin inlines untranslatable layers as base64-encoded PNG sequences. Traditional optimization can't touch this — the leverage is in re-encoding those raster frames to WebP and lowering the effective frame rate. Combined, these two operations typically reduce file size by 50–100×. The Inspector tool on this site quantifies the problem in one drop, and the Compressor solves it without uploading anything.