Dataset guide

sBot-Datasets: dataset guide

Load an episode, choose a task and understand the fields and annotations in the release.

Load one episode

Start with the croissant dataset: 98 demonstrations of moving a croissant onto a plate. Download its metadata and robot data first, about 34 MB. Adding all the videos brings the download to about 2.5 GB. No Hugging Face token is needed.

1. Download the data

Run these commands in a terminal, inside your Python environment:

python -m pip install huggingface_hub pyarrow

hf download L5vel/base4-plate-croissant-eef-merged-v30 \
    --repo-type dataset \
    --include 'meta/**' --include 'data/**' \
    --local-dir ./plate-croissant

2. Read episode 47

Save this as inspect_episode.py beside the downloaded plate-croissant/ directory, then run python inspect_episode.py. It reads one episode’s robot data without decoding video.

import json
from pathlib import Path

import pyarrow.dataset as ds

root = Path("plate-croissant")
info = json.loads((root / "meta/info.json").read_text())
episode_id = 47
frames = ds.dataset(root / "data", format="parquet").to_table(
    columns=["frame_index", "timestamp", "observation.state", "language_persistent"],
    filter=ds.field("episode_index") == episode_id,
).sort_by([("frame_index", "ascending")])

print("Episodes:", info["total_episodes"])
print("Declared rate:", info["fps"], "Hz")
print("State dimensions:", len(frames["observation.state"][0].as_py()))

For this release, the output is:

Episodes: 98
Declared rate: 50 Hz
State dimensions: 10

Continue with the annotation example below to print this episode’s subtask timeline.

Add video with LeRobot

To load images alongside robot state, use a LeRobot installation with dataset support and a working video decoder. Install it in your Python 3.12 environment using this terminal command:

python -m pip install 'lerobot[dataset]'

Run this Python example separately:

from lerobot.datasets.lerobot_dataset import LeRobotDataset

dataset = LeRobotDataset(
    "L5vel/base4-plate-croissant-eef-merged-v30",
    episodes=[47],
)
sample = dataset[0]  # First frame of the selected episode.
print(sample["observation.state"].shape)
print(sample["observation.images.wrist"].shape)

The state has 10 values; the RGB wrist image has shape (3, 480, 640). LeRobot uses its own download cache for this example. Selecting an episode can still fetch shared video or data shards that contain other episodes. Leave room for downloads and video decoding.

Choose a dataset

All ten datasets use LeRobot v3.0 and Apache-2.0. Each has three camera views and robot state and action data. Pick a shorter task to inspect a grasp, or a longer sequence to work with several steps of manipulation and movement. The links below open the full repositories on Hugging Face.

Ten tasks, ordered by total recorded duration
Task and dataset linkEpisodesTypical lengthFull download
grab a drink from the fridge25078 s18.6 GB
clean the table with the green towel19952 s9.6 GB
open the door and move inside20051 s6.8 GB
pick up the bag on the ground and place it on the table20048 s9.3 GB
move the croissant to the empty plate9832 s2.5 GB
open the fridge door10024 s2.2 GB
pick up the grocery bag from the ground10018 s1.5 GB
place the blue cup on the table (+1 more)15011 s1.6 GB
pick up the blue cup from the table10215 s1.4 GB
pick up the green bottle from the table10014 s1.2 GB

Typical length is the median episode duration. Sizes include videos and are rounded. Across the collection: 1,499 episodes, 17.2 hours and 54.9 GB. The detailed table also includes frame counts, duration ranges and annotation sources.

Find the files and fields

These are LeRobot v3.0 datasets. Episode data is packed into shards; one Parquet or video file can contain more than one episode.

data/chunk-*/file-*.parquet          Robot states, actions and language
videos/<camera>/chunk-*/file-*.mp4   Camera recordings
meta/info.json                     Format, features and dataset counts
meta/tasks.parquet                 Task text, looked up by task_index
meta/episodes/                     Episode metadata and success flags
meta/eef_kinematics.json            End-effector representation metadata
Fields used in a typical loading or annotation workflow
FieldShape / typeWhat it contains
observation.state
action
10 values eachSix arm joints, gripper, and base x, y, yaw.
observation.eef_state
action.eef
13 values eachCartesian position, two orientation axes, gripper and base pose. This is the -eef-merged- representation in repository names.
observation.base_pose3 valuesBase x, y and yaw.
observation.images.left
observation.images.right
observation.images.wrist
640×480 RGBTwo scene cameras and one wrist camera. H.264 video, without audio; all streams declare 50 Hz.
language_persistentLanguage messagesThe episode’s complete persistent annotation list, repeated on every frame. Filter by style and timestamp to recover subtasks.
language_eventsLanguage messagesPresent but empty in this release. There are no interjection, speech or VQA events to load.
task_indexTask lookupIdentifies the canonical task text. Read the per-frame value; one dataset contains two task strings.

The common 50 Hz rate describes the stored streams. Physical synchronization error between cameras and other sensors has not been measured.

Metadata differences to handle in a loader
  • Nine repositories list only seven motor names for the 10-value state and action vectors. base4-plate-croissant names all ten; the final three values are base x, y and yaw.
  • task_index_high_level exists only in base4-clean-table, base4-mobile-door, u850-bag-place, u850-fridge-drink and base4-plate-croissant. Make this field optional.
  • The per-frame correction flag is false everywhere. It supplies no marked intervention segments; it does not independently establish that no interventions occurred.

Choose a camera view

These frames show episode 47 of the croissant dataset at the same recorded timestamp, 15.8 seconds. Use the scene views for the arm’s approach and the wrist view for a closer look at the gripper and target.

  • Left scene camera: the arm is lowered over a dark wooden dining table set with plates, a bottle and coloured objects; laboratory benches and a wall display behind.

    observation.images.left640×480, declared 50 Hz

  • Right scene camera at the same recorded timestamp, showing the arm's reach across the table from the opposite side and a dining chair pushed in beside it.

    observation.images.right640×480, declared 50 Hz

  • Wrist camera: looking straight down between the two gripper fingers at a croissant lying on the dark tabletop, with an empty pale-green plate to its left.

    observation.images.wrist640×480, declared 50 Hz

Figure R1 — one moment, three camera views. Croissant episode 47 at 15.8 seconds. The scene cameras show the approach; the wrist camera shows the croissant and destination plate more clearly.

Read subtask annotations

Read the annotation list once per episode. Every frame stores the same complete list in language_persistent. Select messages with style="subtask", then sort them by timestamp. Append this code to inspect_episode.py:

import ast

messages = frames["language_persistent"][0].as_py() or []
messages = [ast.literal_eval(m) if isinstance(m, str) else m for m in messages]
subtasks = sorted(
    (m["timestamp"], m["content"])
    for m in messages if m.get("style") == "subtask"
)

for start, label in subtasks:
    print(f"{start:6.2f} s  {label}")
if not subtasks:
    print("This episode has no subtask annotations.")

You will get one line per subtask: its start time in seconds and its label. Depending on the reader, a message can arrive as a decoded object or a Python-literal string; the example handles both. Read another episode by changing episode_id in the first example.

A subtask lasts until the next subtask’s start; the last one lasts until the episode ends. For example, a step starting at 3.94 seconds followed by a step at 9.00 seconds covers [3.94, 9.00). Do not merge repeated labels: two wiping passes are two separate spans.

Stored message example and the blog’s video source

This message comes from table-cleaning episode 104, shown in the blog. It illustrates the same format used in the croissant walkthrough.

{
  "role": "assistant",
  "content": "move the green towel towards the mess",
  "style": "subtask",
  "timestamp": 3.940000057220459,
  "camera": null,
  "tool_calls": null
}

The cleaning episode uses imported annotations. The records do not identify their original author or establish human verification. The embedded web clip is re-encoded at 25 fps from a dataset stream declared at 50 Hz.

Check annotation sources

The collection combines existing annotations with model-generated annotations. Importing records where labels entered the pipeline; it does not identify who originally wrote or reviewed them.

Subtask annotations across all 1,499 episodes
SourceEpisodesSubtask spansHow to interpret it
Imported, with subtasks8955,201Existing labels were retained; start times were snapped to frames and spans joined to cover the episode.
Generated6021,681Run logs name Qwen3.8-27B, but do not pin an immutable model revision.
Imported, empty track20One episode each in table cleaning and retrieving a drink from the fridge.

Independent annotation agreement and downstream training gains have not been measured for this release. The timing study evaluates fixed-label predictions against source references; it does not measure the quality of the generated labels published here.

Annotation source for each dataset
Processing route recorded for each dataset
DatasetSubtask source
u850-fridge-drinkImport route (249 with spans; 1 empty)
base4-clean-tableImport route (198 with spans; 1 empty)
base4-mobile-doorMixed (150 import route; 50 Qwen generation route)
u850-bag-placeImport route (200 with spans)
base4-plate-croissantImport route (98 with spans)
u850-fridge-openQwen generation route (100 with spans)
base4-mobile-bagQwen generation route (100 with spans)
base4-mobile-place-cupQwen generation route (150 with spans)
base4-mobile-cupQwen generation route (102 with spans)
base4-mobile-bottleQwen generation route (100 with spans)
Task text, paraphrases, plans and memory
  • Canonical task strings come from the source task metadata.
  • Task paraphrases and 5,385 memory rows come from text-only model calls. The component logs name Qwen3.8-27B without a pinned revision.
  • The pipeline targeted ten alternative task descriptions. 1,482 episodes retain ten and 17 retain nine, in addition to the canonical task.
  • Plans are constructed from the published subtask sequence. They are derived annotations, rather than an independent record of the task.
How the release was checked

All 1,499 persistent annotation lists in the ten merged releases match their corresponding outputs across 32 component runs. Import logs show that spans were read from meta/lerobot_annotations.json without a subtask generation call. Label sequences were preserved.

During import, 4,136 of 5,201 start times moved: 4,135 by no more than one 50 Hz frame and one by 0.563 seconds. Ends were rebuilt from the next start and the episode end. These checks establish the publishing process; the records contain no original-author or human-verification field.

Prepare your experiment

  • Split by episode. The published datasets define one train split containing every episode. Create your own training and evaluation split before sampling frames.
  • Choose whether to include unsuccessful episodes. Read the success flag in meta/episodes/; five of the 1,499 episodes are marked unsuccessful.
  • Check labels against video. Wording and timing conventions vary. In base4-mobile-cup, episode 82’s task says “blue cup” while a subtask says “black cup”.
  • Handle missing subtasks. Two episodes have empty tracks. The parsing example above handles this case.
  • Read task text by index. base4-mobile-place-cup contains two canonical task strings. The other nine datasets contain one each.
  • Use repository metadata for the schema. The snapshot’s dataset cards contain boilerplate and some visualization badges point to an older namespace. Use the repository links on this page and inspect meta/.

These recordings come from a working laboratory, with the teleoperator and colleagues sometimes visible. When inspecting or sharing clips, keep that recording context in mind.

Explore collection statistics

Open the sections below for the complete counts and charts. They describe the 9 September 2026 snapshot; recompute them if the repositories change.

Full dataset statistics and recording lengths
The ten datasets published at huggingface.co/L5vel, ordered by recorded duration. All are LeRobot v3.0, 50 Hz, three 640×480 camera views, Apache-2.0.
Dataset Task string Episodes Frames Duration Median episode Range Subtasks/ep Subtask source Size
u850-fridge-drink-eef-merged-v30 grab a drink from the fridge 250 968,523 323 min 78 s 41–105 s 5.8 Import route (249 with spans; 1 empty) 18.6 GB
base4-clean-table-eef-merged-v30 clean the table with the green towel 199 534,608 178 min 52 s 27–236 s 6.2 Import route (198 with spans; 1 empty) 9.6 GB
base4-mobile-door-eef-merged-v30 open the door and move inside 200 506,473 169 min 51 s 40–68 s 5.8 Mixed (150 import route; 50 Qwen generation route) 6.8 GB
u850-bag-place-eef-merged-v30 pick up the bag on the ground and place it on the table 200 477,058 159 min 48 s 38–58 s 6.0 Import route (200 with spans) 9.3 GB
base4-plate-croissant-eef-merged-v30 move the croissant to the empty plate 98 155,517 52 min 32 s 23–51 s 4.3 Import route (98 with spans) 2.5 GB
u850-fridge-open-eef-merged-v30 open the fridge door 100 118,990 40 min 24 s 16–32 s 3.6 Qwen generation route (100 with spans) 2.2 GB
base4-mobile-bag-eef-merged-v30 pick up the grocery bag from the ground 100 92,672 31 min 18 s 12–27 s 2.6 Qwen generation route (100 with spans) 1.5 GB
base4-mobile-place-cup-eef-merged-v30 place the blue cup on the table (+1 more) 150 90,017 30 min 11 s 8–24 s 2.3 Qwen generation route (150 with spans) 1.6 GB
base4-mobile-cup-eef-merged-v30 pick up the blue cup from the table 102 75,870 25 min 15 s 11–21 s 2.5 Qwen generation route (102 with spans) 1.4 GB
base4-mobile-bottle-eef-merged-v30 pick up the green bottle from the table 100 69,748 23 min 14 s 8–24 s 1.9 Qwen generation route (100 with spans) 1.2 GB
All ten — 1,499 3,089,476 17.2 h — 8–236 s 4.6 897 import route (895 with spans; 2 empty); 602 Qwen generation route 54.9 GB

Episodes, frames and task strings come from meta/info.json and meta/tasks.parquet. Duration is frame count divided by the declared 50 fps. Episode lengths come from meta/episodes/; sizes sum the repository file tree. Subtasks per episode includes empty tracks.

Recorded duration and episode count per datasetHorizontal bar chart. Each of the ten L5VEL datasets is drawn as a bar whose length is its recorded duration in minutes, computed as total frames divided by 50 frames per second. u850-fridge-drink is largest at 323 minutes over 250 episodes; base4-mobile-bottle is smallest at 23 minutes over 100 episodes. Together the ten hold 1,499 episodes and 17.2 hours. Recorded duration per dataset minutes of 50 Hz recording · episode count and on-disk size at right 0 60 120 180 240 300 u850-fridge-drink 323 min 250 ep · 18.6 GB base4-clean-table 178 min 199 ep · 9.6 GB base4-mobile-door 169 min 200 ep · 6.8 GB u850-bag-place 159 min 200 ep · 9.3 GB base4-plate-croissant 52 min 98 ep · 2.5 GB u850-fridge-open 40 min 100 ep · 2.2 GB base4-mobile-bag 31 min 100 ep · 1.5 GB base4-mobile-place-cup 30 min 150 ep · 1.6 GB base4-mobile-cup 25 min 102 ep · 1.4 GB base4-mobile-bottle 23 min 100 ep · 1.2 GB Total: 1,499 episodes · 3,089,476 frames · 17.2 h · 54.9 GB
Figure R2 — the collection is dominated by four datasets. u850-fridge-drink alone holds more recorded time than the five smallest combined. If you are looking for long-horizon episodes, the top four rows are where they are; if you want shorter trajectories, the bottom five. Source: total frames ÷ 50 fps from each dataset's meta/info.json; episode counts and file sizes from the Hugging Face repository tree.
Episode-length distribution for each datasetBox plot on a logarithmic time axis. For each dataset a box spans the 25th to 75th percentile of episode length, a white tick marks the median, and whiskers reach the 5th and 95th percentiles; minimum and maximum are shown as small dots. Median episode length ranges from 11.5 seconds for base4-mobile-place-cup to 77.6 seconds for u850-fridge-drink. Computed over all 1,499 episodes. Episode length, all 1,499 episodes box = interquartile range · tick = median · whiskers = 5th–95th percentile · dots = min and max 10s 20s 30s 60s 120s 240s u850-fridge-drink n=250 · med 78s base4-clean-table n=199 · med 52s base4-mobile-door n=200 · med 51s u850-bag-place n=200 · med 48s base4-plate-croissant n=98 · med 32s u850-fridge-open n=100 · med 24s base4-mobile-bag n=100 · med 18s base4-mobile-cup n=102 · med 15s base4-mobile-bottle n=100 · med 14s base4-mobile-place-cup n=150 · med 11s Time axis is logarithmic. Longest single episode: 236 s (base4-clean-table).
Figure R3 — episode length separates the collection into two regimes. Six shorter-horizon datasets have medians from 11 to 32 seconds with relatively little spread. base4-clean-table has the broadest length distribution and the longest single episode: its interquartile range spans 42–63 seconds and its maximum is 236 seconds. Its 52-second median is close to base4-mobile-door's 51 seconds and below u850-fridge-drink's 78 seconds. The time axis is logarithmic. Source: the length column of meta/episodes/ for all 1,499 episodes, divided by the declared 50 fps.
Representative wrist views for all ten tasks
  • Wrist camera: the gripper holds a folded teal towel flat against a white desktop, a blue spray bottle beyond it.

    base4-clean-table“clean the table with the green towel” · episode 104, t = 29 s

  • Wrist camera: inside a refrigerator, the gripper closes around one of three red drink cans on a white shelf.

    u850-fridge-drink“grab a drink from the fridge” · episode 65, t = 43 s

  • Wrist camera: the gripper is level with the lever handle of a heavy grey door standing ajar, carpeted floor and a whiteboard visible through the gap.

    base4-mobile-door“open the door and move inside” · episode 26, t = 23 s

  • Wrist camera: the gripper closes on the folded handles of a woven jute bag.

    u850-bag-place“pick up the bag on the ground and place it on the table” · episode 89, t = 22 s

  • Wrist camera: the gripper is centred over a croissant on a dark wooden table, an empty green plate beside it.

    base4-plate-croissant“move the croissant to the empty plate” · episode 47, t = 14 s

  • Wrist camera: the gripper grips the edge of an opened white refrigerator door; an open laboratory with benches and a second robot lies beyond it.

    u850-fridge-open“open the fridge door” · episode 21, t = 11 s

  • Wrist camera: the gripper hovers above a folded brown paper grocery bag lying on the laboratory floor.

    base4-mobile-bag“pick up the grocery bag from the ground” · episode 45, t = 6 s

  • Wrist camera: the gripper is positioned over a dark cup and a pink bottle standing on a black workbench.

    base4-mobile-place-cup“place the blue cup on the table” · episode 34, t = 6 s

  • Wrist camera: the gripper descends toward a dark cup on a slotted black workbench, the laboratory behind it.

    base4-mobile-cup“pick up the blue cup from the table” · episode 27, t = 7 s

  • Wrist camera: the gripper closes on a green sports bottle with an orange cap standing on a wooden table.

    base4-mobile-bottle“pick up the green bottle from the table” · episode 30, t = 6 s

Figure R4 — ten tasks, one wrist frame each. A representative frame from a median-length successful episode of each dataset, sampled partway through the episode. Objects are ordinary and cluttered rather than staged: a jute bag, a paper grocery bag, drink cans on a fridge shelf, a croissant on a dining table. Source: frames decoded from the observation.images.wrist video of each dataset at the episode and offset noted under each tile.
How many subtasks does each episode contain?
Distribution of subtask count per episode, by datasetStacked horizontal bars. For each dataset the bar shows what fraction of its episodes were segmented into 0 through 8 subtasks. Import-route repositories average 4.3 to 6.2 spans per episode; generation-route repositories average 1.9 to 3.6; mixed base4-mobile-door averages 5.8. Across all 1,499 episodes the ten datasets carry 6,882 spans, so processing route confounds comparisons with task complexity. Subtasks per episode share of each dataset’s episodes, by number of subtask spans in language_persistent 0 1 2 3 4 5 6 7 8 subtasks base4-clean-table mean 6.2 · 7 distinct labels u850-bag-place mean 6.0 · 7 distinct labels u850-fridge-drink mean 5.8 · 9 distinct labels base4-mobile-door mean 5.8 · 42 distinct labels base4-plate-croissant mean 4.3 · 8 distinct labels u850-fridge-open mean 3.6 · 77 distinct labels base4-mobile-bag mean 2.6 · 27 distinct labels base4-mobile-cup mean 2.5 · 65 distinct labels base4-mobile-place-cup mean 2.3 · 104 distinct labels base4-mobile-bottle mean 1.9 · 12 distinct labels 6,882 subtask spans over 1,499 episodes (mean 4.6 per episode). Label vocabulary varies widely between datasets; see the variation section.
Figure R5 — span density and label vocabulary vary across the collection. The four long-horizon datasets sit at five to seven subtasks per episode; the short mobile-manipulation datasets sit at two to three. The vocabulary count is strongly confounded by annotation source: base4-mobile-place-cup uses 104 distinct subtask strings across only 342 spans, while u850-bag-place uses 7 across 1,198. Treat the labels as free text, not as a closed vocabulary — and see the next section for how far this ratio varies across the collection. The generation-route repositories occupy the high-rewording group, import-route repositories occupy the low group, and the mixed door repository lies between them. Source: every subtask entry in language_persistent, parsed from every data shard of all ten datasets — 6,882 spans over 1,499 episodes.
How label wording and timestamp precision vary

Treat the labels as free text. Some datasets reuse a small vocabulary; others describe similar actions in many ways. Timestamp precision also varies, even though every published start falls on a frame.

Two measures of annotation variation, ordered by label reuse. Label reuse uses all 6,882 spans; tick percentages use 5,385 internal span starts, excluding the first start in each of the 1,497 annotated episodes.
Dataset Distinct labels per span Internal starts on a 0.1 s tick
u850-fridge-drink 0.006 18.9%
u850-bag-place 0.006 19.9%
base4-clean-table 0.006 20.2%
base4-plate-croissant 0.019 21.7%
base4-mobile-door 0.036 30.6%
base4-mobile-bottle 0.065 66.3%
base4-mobile-bag 0.105 47.8%
u850-fridge-open 0.214 70.8%
base4-mobile-cup 0.250 71.5%
base4-mobile-place-cup 0.304 53.1%

Label reuse. Distinct subtask strings divided by total spans. Four datasets reuse a small fixed vocabulary (0.006–0.019), five re-word far more freely (0.065–0.304), and base4-mobile-door falls between them at 0.036. At the far end, base4-mobile-place-cup uses 104 distinct strings across 342 spans. Timing granularity. Every span start lands on a frame (a multiple of 0.02 s at 50 Hz). In some datasets about 20% of internal starts also fall on a round tenth of a second — the fraction expected for uniformly distributed positions on a 0.02 s grid — while in others it is 48–72%, which is what a coarser one-decimal timing convention snapped to frames would look like.

The two measures rank the datasets similarly, and that ranking largely follows the recorded processing route: the four import-route repositories occupy the low-vocabulary, roughly 20% tick group; the five generation-route repositories occupy the higher group; and mixed base4-mobile-door lies between them. This association makes provenance a clear confound, but it does not isolate generation from differences in task, source data or preparation. Treat subtask labels as free text, do not assume a single timing convention, and check any desired label vocabulary per dataset.

← Back to the blog

Working with robot data?

Tell us what you’re building with the data, or share an episode that the annotation tool found difficult.

support@l5vel.com