# Figma Motion Export JSON

_September 1, 2026 · 11 min read · by Systergon_

> Getting a JSON file out of a Figma Motion animation and into a codebase: which export produces a file rather than a clipboard string, what it is called, where it lands, and the handful of lines a developer needs to make it play.

**Answers the question:** figma motion export json

**What this page is for:** How to export a Figma Motion animation as a JSON file — copy versus download, the file name and MIME type, and the code that loads the result in lottie-web, lottie-ios, lottie-android and React Native.

URL: https://systergon.com/figma-motion-export-json
Plugin: Motion Path for Figma — https://systergon.com/products/figma-plugins/motion-path
Install: https://www.figma.com/community/plugin/1654530170219655744

## Steps at a glance

1. **Apply the motion path** — The exports read the applied timeline.
2. **Open Copy as code** — Click ⋯ in the titlebar and choose Copy as code.
3. **Select the Lottie tab** — Lottie is the JSON that plays. The other tabs emit CSS, SVG and a demo page.
4. **Download the file** — The download icon saves motion-path.json with an application/json MIME type.
5. **Load it in a player** — Point lottie-web, lottie-ios, lottie-android or lottie-react-native at the file.

---

[Install Motion Path — it’s free →](https://www.figma.com/community/plugin/1654530170219655744) [See the product page](https://systergon.com/products/figma-plugins/motion-path)

**The short answer:** apply your motion with [Motion Path](https://systergon.com/products/figma-plugins/motion-path), open **… → Copy as code**, select the **Lottie** tab, and press the **download** icon in the panel header. You get `motion-path.json` — a Lottie 5.9 document with an `application/json` MIME type — which drops straight into lottie-web, lottie-ios, lottie-android or lottie-react-native with about five lines of code.

This page is the practical one: getting a real file onto disk with the right name, knowing what is inside it, and the code on each platform that makes it play. If you are not yet sure _which_ JSON you want, read [the three-JSONs comparison](https://systergon.com/figma-motion-to-json) first — there are two others in the same menu and only this one runs.

## Copy puts it on the clipboard; download puts it on disk

Two icon buttons sit in the header of the _Copy as code_ panel, and they act on whichever tab is selected. The content is byte-identical. The only difference is where it lands, and that difference matters more than it sounds.

![Two cards comparing the copy button, which puts the JSON on the clipboard for pasting into a chat or ticket, with the download button, which saves motion-path.json to disk with the correct name and MIME type](https://systergon.com/motion-guides/diagrams/copy-or-download.svg)

**Copy** is right when the JSON is going into a message, a ticket, or a scratch file you are about to paste into. **Download** is right when the file is going into a repository. Downloading matters there because it arrives correctly named and correctly typed — a clipboard paste into an editor gets whatever name and extension you happen to give it, and a `.txt` in an assets folder is a small bug waiting to happen at bundle time.

## Getting the file, in four steps

**1. Apply the motion.** The preview in the panel writes nothing to the canvas; the exports read the applied timeline. If you skip this the export has nothing to describe.

![The Motion Path Animate tab: an object riding an S-curve in the preview, Source and Animate rows, Essentials with duration, direction, loops and easing, and the blue Apply motion path button](https://systergon.com/motion-guides/shots/animate-tab.png)

**2. Open Copy as code** from the **…** menu in the titlebar.

![The Motion Path panel with the overflow menu open, listing Save as preset, Copy as code, Export video, Config JSON, Settings and Help](https://systergon.com/motion-guides/shots/menu-open.png)

**3. Select the Lottie tab.** The panel opens on CSS. Four tabs are offered, and only one of them is a JSON document that plays.

![The Copy as code panel with the Lottie tab selected: a description of the Lottie document for iOS, Android, React Native and web reading 60 frames at 60 fps, a code box beginning with version 5.9.0, and a note about the placeholder shape](https://systergon.com/motion-guides/shots/copy-as-lottie.png)

**4. Press download.** The file saves as `motion-path.json`. Rename it to something meaningful on the way into your repository — `checkout-success.json` rather than `motion-path.json` — because you will have several before long and they will all have the same name.

![A step-by-step loop: the Animate tab ready to apply, the overflow menu opening to reveal Copy as code, the panel showing CSS by default, and the Lottie tab selected with the generated JSON](https://systergon.com/motion-guides/shots/steps-lottie.gif)

## What you just downloaded

It is worth spending thirty seconds inside the file, because a developer who understands its shape can debug it and one who does not will file a bug against your design.

![The exported Lottie JSON annotated: v is the schema version, fr the frame rate, ip and op the in and out points, w and h the composition box, and ks the layer transform holding position, rotation, opacity and scale tracks](https://systergon.com/motion-guides/diagrams/lottie-anatomy.svg)

Six top-level fields and an array. `v` is the schema version — 5.9.0, which every current player reads. `fr` is the frame rate, `ip` and `op` the in and out points that give the composition its length, `w` and `h` the composition box derived from the path’s bounding box plus your object’s size.

Then `layers`, and inside the first layer, `ks`: the transform. Position, rotation, opacity and scale tracks. **All of the motion is there** — on the transform, not in the shape. The shape itself is a placeholder sized to your object, which is the single most important thing to communicate downstream.

## Making it play

The integration is short on every platform, and it is the same file in each case.

![Two code snippets: lottie-web loading the JSON with loadAnimation and a path, and lottie-react-native rendering it with a source prop, with a note that loop is a player setting rather than a property of the file](https://systergon.com/motion-guides/diagrams/json-to-code.svg)

**Web.** Install `lottie-web`, then `lottie.loadAnimation({ container, path: '/motion-path.json', loop: true, autoplay: true })`. Serve the JSON as a static asset; it is plain text and caches like any other.

**React Native.** Install `lottie-react-native`, then ``. The `require` bundles it, so there is no fetch to fail.

**iOS.** Add the JSON to the app bundle and load it with `LottieAnimationView(name: "motion-path")`. Playback, speed and loop mode are properties on the view.

**Android.** Put the JSON in `src/main/assets` and point a `LottieAnimationView` at it with `app:lottie_fileName`, or load it in code. Same file, same result.

![A pipeline from Figma Motion through Motion Path to a Lottie 5.9 document, shipping to lottie-ios, lottie-android, React Native and lottie-web](https://systergon.com/motion-guides/diagrams/lottie-pipeline.svg)

## Three things to say when you send it

These are the questions that come back if you do not say them up front, and each of them costs a round trip.

**The shape is a placeholder.** The moving layer is a rectangle sized to your object, not your artwork. Swap it for the real asset, or parent the asset to that transform, and every bit of the motion carries over. This is deliberate rather than a limitation — it is what lets the same motion drive different artwork.

**Looping is a player setting.** The JSON holds one clean pass. `loop: true` in lottie-web, the `loop` prop in React Native, `loopMode` on iOS. If your Figma animation repeated the traversal, the export notes say so explicitly.

**The notes list what is missing.** Forward them with the file. They name any effect in your animation that Lottie cannot carry, so nothing is discovered late.

![Two lists: carried into Lottie are position along the path, rotation, opacity ramp, scale ramp, easing and speed profile, and arc-length travel; left behind are colour shift, motion blur, motion trail, squash and stretch, anticipation and overshoot, and loop count](https://systergon.com/motion-guides/diagrams/what-survives.svg)

## Checking it before it reaches a build

A JSON that parses is not a JSON that plays correctly, and the gap between the two is where a designer’s credibility goes. The check is cheap: load the file into a Lottie player and watch it beside the plugin’s own preview.

That is exactly how the export itself was validated rather than assumed. Loaded into lottie-web, an object on a circular path holds a constant radius from the centre to within a fraction of a pixel; the facing sweeps a clean 360°; and the frame spacing is visibly uneven under an ease — which is what “the easing lives in the timing” should look like when you inspect it. Those are falsifiable claims, and they were checked against a real player rather than by reading the JSON and deciding it looked plausible.

Three things are worth eyeballing on your own file. Does it start and end where you expect — not one frame short, not holding a beat you did not intend? Does the speed look constant where you drew a constant path, rather than crawling through a dense cluster of vertices? And does the composition box frame the motion, rather than clipping it at the edges?

The comparison is fair, incidentally, because the preview and the export are not two implementations of the same idea:

![One resolved path and timing feeding three outputs: the inline preview, the native Figma keyframes, and the CSS, SVG and Lottie exports](https://systergon.com/motion-guides/diagrams/preview-fidelity.svg)

The preview, the canvas keyframes and every export come from one resolved polyline and one timing model. They cannot drift apart, because there is nothing separate to drift.

## Keeping the file current

Nothing here creates a live link. The JSON is a snapshot taken when you pressed the button, and when the design changes the file does not. That is obvious written down and still surprises teams three sprints later, when the shipped animation is quietly not the one in the Figma file.

The habit that makes it survivable is to **re-export rather than hand-edit**. A JSON a developer has tweaked by hand cannot be regenerated without losing the tweak, and the moment that happens the Figma file has stopped being the source of truth — nobody announces it, it just becomes true. Re-exporting is cheap; that is much of why the plugin writes native Figma keyframes instead of running its own engine.

If a value genuinely needs to differ at runtime — speed, say, or where the animation pauses — that belongs in the player rather than in the file. Every Lottie player exposes speed, direction, and the ability to play a frame range, so a developer can hold the animation at 40% while a form validates without touching the JSON at all. That is a capability a video simply does not have, and it is worth pointing out when someone asks why you did not just send an MP4.

## Where the file belongs in a repository

This is a small question that causes a surprising amount of friction, because designers hand over a file and engineers have to decide what it _is_ before they can put it anywhere.

A Lottie is a static asset, not source code. On the web it belongs wherever images live and gets served with the same caching rules; it is plain text, so it gzips well and a CDN handles it without special treatment. In a React Native app it is usually bundled through `require` so there is no network fetch to fail on a cold start. On iOS it goes in the app bundle; on Android, in `src/main/assets`.

The decision that actually matters is bundle versus fetch. Bundling means the animation is guaranteed present and costs app size; fetching means it can be updated without a release and can fail. For a small interface animation — a success tick, a loading state — bundling is nearly always right, because the failure case of a missing animation at exactly the moment the user needs feedback is worse than a few kilobytes.

One thing worth agreeing early: who owns the file after handoff. If the answer is “the designer, and it is regenerated from Figma”, then nobody should be editing it in the repository and it is worth saying so in the pull request. If the answer is “engineering owns it now”, that is a legitimate choice too — but it means the Figma file is a reference rather than a source, and everyone should know that before the first divergence rather than after it.

## The two JSONs you probably did not want

The same **…** menu has a **Config JSON** item, and Figma itself has _Copy as → JSON_. Neither plays.

![The Config JSON panel: a Copy config JSON button, a text area reading Paste config JSON here, and a disabled Apply pasted JSON button](https://systergon.com/motion-guides/shots/config-json.png)

**Config JSON** holds the plugin settings that produced the motion — duration, easing, direction, effects — so a colleague can paste it and rebuild the same recipe on their own path. It is a good thing to send alongside a Lottie when a technique will be reused, and a useless thing to send instead of one.

**Figma’s Copy as → JSON** gives Figma’s own description of the native keyframes on the layer. It works on a Motion Path animation because the plugin writes native tracks rather than running its own engine. It is the right choice when a developer is already in Dev Mode and wants Figma’s representation; no Lottie player will read it.

![Three cards comparing the JSON outputs: Lottie JSON which plays, Figma's Copy as JSON which describes the Motion keyframes, and Config JSON which reproduces the plugin setup](https://systergon.com/motion-guides/diagrams/three-jsons.svg)

The quickest way to tell which file you are holding: a Lottie starts with `"v"`, `"fr"`, `"ip"`, `"op"` and has a `"layers"` array. If there is no `layers` key, it is not an animation.

## Frequently asked questions

### How do I export JSON from a Figma Motion animation?

Apply the motion, open **… → Copy as code** in Motion Path, select the **Lottie** tab, and press the download icon. The file saves as `motion-path.json`.

### What is the exported file called and where does it go?

`motion-path.json`, with an `application/json` MIME type, saved to your browser’s download location. Rename it to something meaningful before it enters a repository — every export has the same default name.

### Is the JSON a Lottie file?

Yes — a Lottie 5.9 document. Every Lottie is JSON, but not every JSON is Lottie: the other two JSONs in this workflow are not animations and no player will read them.

### How do I play the JSON on the web?

Install `lottie-web` and call `lottie.loadAnimation({ container, path: '/motion-path.json', loop: true, autoplay: true })`. Serve the JSON as a static asset.

### Does the JSON include my artwork?

No. It carries a placeholder shape sized to your object, because the motion lives on the layer transform rather than in the shape. A developer swaps the placeholder for the real asset and the motion is unchanged.

### Can I make it loop?

Yes, in the player. The file holds one pass of the motion; `loop: true` in lottie-web, the `loop` prop in React Native, `loopMode` on iOS, and the equivalent on Android.

### Why is the file so large?

Because Lottie has no `offset-path` equivalent, so a curve has to be sampled point by point rather than expressed as two keyframes and a timing function. It is repetitive numeric text and compresses very well over the wire — typically still smaller than the MP4 of the same animation, and unlike the MP4 it is resolution-free.

### Can I edit the JSON by hand afterwards?

You can, but it makes the file unregenerable: the next re-export loses your edit, and in practice the Figma file quietly stops being the source of truth. Change it in Figma and export again, or handle the difference in the player.

### Does this work for text animated along a path?

Yes. The Text tab has its own export in the same place, and it carries the letter-by-letter cascade as one Lottie layer per glyph, with the stagger baked into their timing.

## Where to go next

- [Figma Motion to JSON](https://systergon.com/figma-motion-to-json) — the three JSONs compared, if you are still choosing.
- [Figma Motion export Lottie](https://systergon.com/figma-motion-export-lottie) — the developer handoff conversation in full.
- [Figma Motion Lottie export](https://systergon.com/figma-motion-lottie-export) — a field-by-field panel reference.
- [How to export Figma Motion](https://systergon.com/how-to-export-figma-motion) — every route out, compared.
- [Motion Path help centre](https://systergon.com/motion-path/help) — paths, timing, effects and troubleshooting.

[Install Motion Path — it’s free →](https://www.figma.com/community/plugin/1654530170219655744) [Browse 300+ animation examples](https://systergon.com/motion-path/examples)

## Related guides

- [Figma Motion to JSON](https://systergon.com/figma-motion-to-json) — Explains the three JSON outputs available from a Figma Motion animation — Lottie JSON, Figma’s own Copy as JSON, and Motion Path’s Config JSON — and which one to use for playback, inspection or reproducing a setup.
- [Figma Motion Export Lottie](https://systergon.com/figma-motion-export-lottie) — The developer handoff for a Lottie exported from Figma Motion — what the engineer receives, how each platform player loads it, and the caveats to communicate about looping, artwork and unsupported effects.
- [Figma Motion Lottie Export](https://systergon.com/figma-motion-lottie-export) — A reference for the Lottie export panel in Motion Path — the tab layout, the copy and download buttons, the structure of the emitted Lottie 5.9 document, and the notes that list what was left out.
- [How to Export Figma Motion](https://systergon.com/how-to-export-figma-motion) — The hub page for exporting Figma Motion: compares every available route — MP4, GIF, WebM, Lottie, CSS, SVG, HTML, Figma’s native Copy as, and Config JSON — and says which to pick for a given destination.
