Download a motion for Unitree G1
The Unitree G1 CSV export is not yet covered by the official Python (uthana) or JavaScript (@uthana/client) clients. Use the raw HTTP examples below with your API key for Basic auth.
Use this export when you want to run a Uthana-generated motion on a Unitree G1 humanoid robot. The result is a .csv file containing the robot trajectory for the selected motion.
You still provide both IDs in the URL:
motionIdselects the motion to export.characterIdis required for access, quotas, and billing. It does not change the output format—the response is always for Unitree G1.
For standard character animation files, use Download a motion instead.
HTTP endpoint and filename
Send a GET request with Basic auth using your API key:
https://uthana.com/motion/file/motion_viewer/{characterId}/{motionId}/csv/{anyname}.csv
The last path segment is only part of the route. You can use any .csv name there, such as export.csv.
The response sets this download filename in Content-Disposition:
unitree_g1_{characterId}-{motionId}.csv
Save the file with that name, or read the Content-Disposition header from your HTTP client. The response body is plain text/csv.
Query parameters
fps:24,30, or60. If omitted, the export uses 30 FPS.
Unitree G1 CSV downloads do not support any other query parameters.
Using the CSV on a Unitree G1
The downloaded .csv is intended to be consumed by your robot-side playback or control workflow. In practice, you will usually:
- Download the CSV from Uthana.
- Copy it to the development computer or runtime environment you use with the G1.
- Load the CSV in your own playback/controller code and send the trajectory through the appropriate Unitree control interface.
For robot setup, networking, SDK installation, and controller integration, use Unitree's G1 developer documentation as the source of truth: Unitree G1 developer docs.
Latency and timeouts
This export can take longer than a typical FBX or GLB download. As a rough planning estimate, expect a 10s motion to take 5-10 seconds to process.
Example requests
- Shell
- Python
- TypeScript
- C#
API_KEY="YOUR_API_KEY"
CHARACTER_ID="cXi2eAP19XwQ"
MOTION_ID="your-motion-id"
# Optional: ?fps=30|24|60
curl -L "https://uthana.com/motion/file/motion_viewer/${CHARACTER_ID}/${MOTION_ID}/csv/motion.csv?fps=30" \
-u "$API_KEY:" \
-o "unitree_g1_${CHARACTER_ID}-${MOTION_ID}.csv"
import requests
API_KEY = "YOUR_API_KEY"
CHARACTER_ID = "cXi2eAP19XwQ"
MOTION_ID = "your-motion-id"
url = f"https://uthana.com/motion/file/motion_viewer/{CHARACTER_ID}/{MOTION_ID}/csv/export.csv?fps=30"
response = requests.get(url, auth=(API_KEY, ""), timeout=600)
response.raise_for_status()
out_name = f"unitree_g1_{CHARACTER_ID}-{MOTION_ID}.csv"
with open(out_name, "wb") as f:
f.write(response.content)
const API_KEY = "YOUR_API_KEY";
const CHARACTER_ID = "cXi2eAP19XwQ";
const MOTION_ID = "your-motion-id";
const authString = btoa(`${API_KEY}:`);
const url = `https://uthana.com/motion/file/motion_viewer/${CHARACTER_ID}/${MOTION_ID}/csv/export.csv?fps=30`;
const response = await fetch(url, {
headers: { Authorization: `Basic ${authString}` },
});
if (!response.ok) throw new Error(String(response.status));
const buffer = await response.arrayBuffer();
// Save as unitree_g1_{CHARACTER_ID}-${MOTION_ID}.csv
var apiKey = "YOUR_API_KEY";
var characterId = "cXi2eAP19XwQ";
var motionId = "your-motion-id";
var downloadUrl = $"https://uthana.com/motion/file/motion_viewer/{characterId}/{motionId}/csv/motion.csv?fps=30";
var auth = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{apiKey}:"));
_httpClient.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", auth);
var response = await _httpClient.GetAsync(downloadUrl);
response.EnsureSuccessStatusCode();
var bytes = await response.Content.ReadAsByteArrayAsync();
// Save as unitree_g1_{characterId}-{motionId}.csv
Related
- Download a motion — General FBX, GLB, and BVH downloads and options
- GraphQL API reference — Includes motion download URL patterns