On this page

Apply motions generated with Uthana to your custom 3D characters. Retargeting automatically adapts animations to work with different character skeletons and proportions.

## Overview

When you generate a motion with Uthana, it's created for a specific character skeleton. Retargeting allows you to apply that same motion to any character you've uploaded, automatically adapting the animation to match different bone structures and proportions.

Learn more about [Retargeting](/content/product/flexible-retargeting/index.html).

## How retargeting works

1. **Generate or select a motion**: Create a motion using text-to-motion, locomotion, or video-to-motion, or use an existing motion
2. **Choose your character**: Select the character you want to apply the motion to
3. **Download the retargeted motion**: The motion is automatically retargeted when you download it with a specific character ID

## Step-by-step tutorial

### Step 1: Upload your character

First, upload your custom character model. Uthana will automatically rig it if needed.

See the [Auto-rig / add a character](/content/docs/api/capabilities/auto-rig-and-add-character/index.html) guide for detailed instructions on uploading characters, including supported formats, auto-rigging options, and code examples for all languages.

After uploading, save the character ID from the response. You'll need it for retargeting motions.

### Step 2: Generate a motion

Generate a motion using [Text to motion](/content/docs/api/capabilities/text-to-motion/index.html), [Locomotion](/content/docs/api/capabilities/locomotion/index.html), or [Video to motion](/content/docs/api/capabilities/video-to-motion/index.html). Save the motion ID from the response—you'll need it for downloading the retargeted motion.

### Step 3: Download retargeted motion

When you download a motion with a specific character ID, Uthana automatically retargets it to that character's skeleton.

```shell
# Download retargeted motion as FBX (filename is customizable)
curl -L "https://uthana.com/motion/file/motion_viewer/$CHARACTER_ID/$MOTION_ID/fbx/motion.fbx" \
  -u $API_KEY: \
  -o retargeted-motion.fbx

# Download retargeted motion as GLB (filename is customizable)
curl -L "https://uthana.com/motion/file/motion_viewer/$CHARACTER_ID/$MOTION_ID/glb/motion.glb" \
  -u $API_KEY: \
  -o retargeted-motion.glb
```

```python
import asyncio
from uthana import Uthana

client = Uthana("{{apiKey}}")

async def main():
    # Download retargeted motion as FBX for a specific character
    fbx_data = await client.motions.download(CHARACTER_ID, MOTION_ID, output_format="fbx")
    with open("retargeted-motion.fbx", "wb") as f:
        f.write(fbx_data)

# Download retargeted motion as GLB
    glb_data = await client.motions.download(CHARACTER_ID, MOTION_ID, output_format="glb")
    with open("retargeted-motion.glb", "wb") as f:
        f.write(glb_data)

asyncio.run(main())
```

```typescript
import { UthanaClient } from "@uthana/client";

const client = new UthanaClient(process.env.UTHANA_API_KEY!);

// Download retargeted motion as FBX for a specific character
const fbxBuffer = await client.motions.download(CHARACTER_ID, MOTION_ID, { output_format: "fbx" });

// Download retargeted motion as GLB
const glbBuffer = await client.motions.download(CHARACTER_ID, MOTION_ID, { output_format: "glb" });
```

```typescript
import { useUthanaClient } from "@uthana/react";

function DownloadRetargetedMotion({
  characterId,
  motionId,
}: {
  characterId: string;
  motionId: string;
}) {
  const client = useUthanaClient();

async function download(format: "glb" | "fbx") {
    const buffer = await client.motions.download(characterId, motionId, { output_format: format });
    const mime = format === "glb" ? "model/gltf-binary" : "application/octet-stream";
    const url = URL.createObjectURL(new Blob([buffer], { type: mime }));
    const a = document.createElement("a");
    a.href = url;
    a.download = `retargeted-motion.${format}`;
    a.click();
  }

return (
    <div>
      <button onClick={() => download("fbx")}>Download FBX</button>
      <button onClick={() => download("glb")}>Download GLB</button>
    </div>
  );
}
```

```csharp
public async Task<byte[]> DownloadRetargetedMotionAsync(string characterId, string motionId, string format = "fbx", string filename = "motion")
{
    var downloadUrl = $
