Open X-Embodiment publishes no per-dataset licence. Its README licenses all software under Apache 2.0 and all other materials under CC BY 4.0 under a 2023 copyright line for that repository, the LICENSE file beside it is the Apache text alone so the GitHub badge reads Apache-2.0, the project website contains zero occurrences of the string licen, the 72-row dataset spreadsheet has 22 columns and none of them is a licence column, and the TFDS metadata shipped in the public release bucket omits redistribution_info, the one field the format reserves for licence text. Downstream, 1,876 of the 2,000 most-downloaded LeRobot-format datasets on Hugging Face read apache-2.0, because LeRobotDataset.push_to_hub carries a license parameter defaulting to apache-2.0 and lerobot-record never passes one. That default contradicts three upstream projects that did state terms: BridgeData V2 and DROID both say CC BY 4.0, and the LIBERO README states MIT for the codebase and CC BY 4.0 for the datasets. 13 of those 2,000 rows carry a non-commercial licence, which is the class that bites an on-premise deployment whether or not a byte leaves the building. Start by running the audit over the corpora already in your training mix and opening the upstream page for every row that reads apache-2.0.
Open X-Embodiment does not have a licence. It has five primary documents, none of which states a per-dataset term, and 72 constituent datasets contributed by dozens of labs. Whether Open X-Embodiment dataset licence terms clear commercial use is a question you ask once per constituent, against whatever the originating project wrote down.
The catalogue downstream of it looks far more settled, and the tidiness is an artifact. Of the 2,000 most-downloaded LeRobot-format datasets on Hugging Face, 1,876 read apache-2.0. The cause is mechanical: LeRobotDataset.push_to_hub carries a license parameter defaulting to apache-2.0, the record script calls it without passing one, and the config behind the CLI has no licence field to override it with. That tag contradicts three upstream projects that did state terms.
What Open X-Embodiment actually licenses, and where it goes blank
Five documents carry the project's terms, and none answers the per-dataset question.
The repository README carries Copyright 2023 DeepMind Technologies Limited. at line 67, licenses all software under the Apache License, Version 2.0 at line 69, and licenses all other materials under the Creative Commons Attribution 4.0 International License at line 71. That copyright line is why the CC BY clause cannot be lifted onto the constituents: the same README asks you to cite contributed datasets separately, treating them as separate works.
The LICENSE file beside it is the Apache 2.0 text and nothing else, which is why the GitHub licence field on google-deepmind/open_x_embodiment returns spdx_id: Apache-2.0. The badge parses one file, the README qualifies it, neither reaches the data. The project website contains zero occurrences of licen.
The canonical spreadsheet, 72 rows across 22 columns with a citation on 69, contains the string licen zero times in its CSV export.
The storage format reserves a field for this and the release omits it. The TFDS DatasetInfo proto defines field 11 as redistribution_info, whose only member is string license = 1, commented "Text to be included in LICENSE file." It is absent from the dataset_info.json of all four constituent builds we checked, and the public bucket carries no top-level LICENSE object.
The Open X-Embodiment paper describes 60 datasets pooled from 34 robotics research labs and has no licensing section. The spreadsheet now lists 72 rows, 60 in a v1.0 block and 12 in v1.1, totalling 2,419,193 episodes; how much data a robot policy needs covers that volume.
| Document | What it states about licensing | What it leaves unanswered |
|---|---|---|
| Repository README | Apache 2.0 for software, CC BY 4.0 for all other materials, under a 2023 repository copyright line | Terms for the contributed datasets, which it asks you to cite separately |
| Repository LICENSE file | The Apache 2.0 text alone, which is why the GitHub field reads Apache-2.0 | Anything about data |
| Project website | Nothing. Zero occurrences of the string licen | Everything |
| Dataset spreadsheet, 72 rows, 22 columns | A citation on 69 rows and a registered TFDS name on 69 | No licence column exists |
| TFDS dataset_info.json in the release bucket | citation, description, fileFormat, location, moduleName, name, releaseNotes, splits, version | redistribution_info, the field reserved for licence text, is absent |
The apache-2.0 tag on the Hub is a Python default argument
The standard path from an RLDS build to a LeRobot-format mirror ends in one method, and that method has an opinion about licensing. The conversion is covered in LeRobot vs RLDS vs HDF5; what matters here is the card it writes. In lerobot 0.6.1, LeRobotDataset.push_to_hub declares the licence as a keyword with a default, and the record script calls it with two arguments, neither of which is the licence.
# lerobot/datasets/lerobot_dataset.py, LeRobotDataset
def push_to_hub(
self,
branch: str | None = None,
tags: list | None = None,
license: str | None = "apache-2.0", # the default nobody passes
tag_version: bool = True,
push_videos: bool = True,
private: bool | None = None,
allow_patterns: list[str] | str | None = None,
upload_large_folder: bool = False,
**card_kwargs,
) -> None:
# lerobot/scripts/lerobot_record.py, finally block of the record session
if cfg.dataset.push_to_hub:
if dataset and dataset.num_episodes > 0:
dataset.push_to_hub(tags=cfg.dataset.tags, private=cfg.dataset.private)DatasetRecordConfig declares repo_id, single_task, root, fps, episode_time_s, reset_time_s, num_episodes, video, push_to_hub, private, tags and the image-writer and encoder settings. No licence field, so no command-line flag reaches the parameter. And push_to_hub defaults to True, so publishing is the default behaviour of a recording session.
The tag records which function default was in force at push time, not who collected the episodes or what they granted.
The absence case runs through the same code. create_lerobot_dataset_card builds its card data with license=kwargs.get("license"), and the template renders - **License:** {{ license | default("[More Information Needed]", true)}}. Omit the licence and the dataset ships with no tag, which is how 63 of the LeRobot organisation's 188 datasets ended up with no licence field.
Three corpora where the mirror tag contradicts the upstream statement
BridgeData V2. The project page states verbatim that all data is provided under the Creative Commons Attribution 4.0 International License. The code repository ships an MIT LICENSE over the Software. The most-downloaded conversion, at 234,972 downloads, reads apache-2.0. One corpus, three strings.
DROID. The DROID paper says twice that the full dataset is open-sourced under CC-BY 4.0 license. The policy learning repository is MIT, which is code. The largest conversion, at 539,610 downloads, reads apache-2.0, as do the three other large DROID conversions. Zero occurrences of licen on the project site or its dataset page: the paper is the only place the term appears.
LIBERO. The repository README ends with a License section: a two-row table reading Codebase MIT, Datasets CC BY 4.0. Of the 225 LIBERO-named LeRobot-format datasets in the top 2,000 by downloads, 220 read apache-2.0 and 5 read cc-by-4.0.
Six mirrors, one tag, three different upstream answers: an Apache 2.0 code licence with no data statement, a CC BY 4.0 data statement, and nothing found.
Four conversions of one benchmark carry three different tags, and only the first matches what the benchmark's README states for its datasets. Its card names openvla/modified_libero_rlds as its source, and that source reads mit, LIBERO's codebase licence applied to data. The third hop corrected what the second inherited.
Whether a re-uploader may lawfully relabel a CC BY 4.0 corpus as apache-2.0 is a question for counsel, not a training config. Detect the conflict, record the evidence, route it.
| Hub mirror | 30-day downloads | Declared tag | Upstream statement, and where it lives |
|---|---|---|---|
| IPEC-COMMUNITY/language_table_lerobot | 1,554,543 | apache-2.0 | Apache 2.0 repo LICENSE, no data statement |
| IPEC-COMMUNITY/kuka_lerobot | 594,024 | apache-2.0 | None found |
| IPEC-COMMUNITY/droid_lerobot | 539,610 | apache-2.0 | CC-BY 4.0, stated in arXiv:2403.12945 |
| IPEC-COMMUNITY/bridge_orig_lerobot | 234,972 | apache-2.0 | CC BY 4.0, stated on the project page |
| IPEC-COMMUNITY/fractal20220817_data_lerobot | 177,403 | apache-2.0 | Apache 2.0 repo LICENSE, no data statement |
| IPEC-COMMUNITY/bc_z_lerobot | 108,022 | apache-2.0 | None found |
| Hub dataset | 30-day downloads | Declared tag | Matches the stated data licence |
|---|---|---|---|
| physical-intelligence/libero | 42,289 | cc-by-4.0 | Yes |
| HuggingFaceVLA/libero | 24,087 | apache-2.0 | No |
| openvla/modified_libero_rlds | 13,317 | mit | No, that is the codebase licence |
| lerobot/libero | 11,080 | apache-2.0 | No |
What the LeRobot-format catalogue actually declares
The LeRobot organisation publishes 188 datasets: 63 with no licence field, 60 apache-2.0, 60 mit, 5 cc-by-4.0. A third of the format's home organisation declares nothing. The snapshot over the 2,000 most-downloaded rows is more lopsided.
Those seven rows sum to 2,000 and the catalogue drifts daily, so read the shares as a snapshot.
The script below reproduces the two distributions above; the third call points it at your own organisation.
from collections import Counter
from huggingface_hub import HfApi
api = HfApi()
def audit(**kwargs):
counts = Counter()
for row in api.list_datasets(expand=["cardData", "downloads"], **kwargs):
declared = (row.card_data or {}).get("license") or "NO LICENCE FIELD"
counts[declared] += 1
return counts
print(audit(author="lerobot"))
print(audit(filter="LeRobot", sort="downloads", limit=2000))
print(audit(author="your-org")) # the same view over mirrors you publish
# lerobot org: {'NO LICENCE FIELD': 63, 'apache-2.0': 60, 'mit': 60, 'cc-by-4.0': 5}
# top 2000: {'apache-2.0': 1876, 'mit': 66, 'cc-by-4.0': 28, 'other': 12,
# 'cc-by-nc-4.0': 7, 'cc-by-nc-sa-4.0': 6, 'NO LICENCE FIELD': 5}sort="downloads" is already descending, the Python client has no direction parameter, and expand cannot be combined with full. De-duplicate per dataset before counting: a handful of rows carry the same tag twice.
One organisation makes it concrete: 49 datasets, 3.6 million downloads over thirty days, 29 tagged openx, all 29 reading apache-2.0. The same argument runs a layer up the stack for embedding models, in contextual retrieval versus late chunking.
| Declared tag | Datasets | Share | What a commercial fine-tune has to do about it |
|---|---|---|---|
| apache-2.0 | 1,876 | 93.8% | Open the upstream: this is also the library default |
| mit | 66 | 3.3% | Retain the copyright and permission notice |
| cc-by-4.0 | 28 | 1.4% | Carry the Section 3(a) attribution block if you ever Share |
| other | 12 | 0.6% | Open the LICENSE file named in license_link |
| cc-by-nc-4.0 | 7 | 0.35% | Commercial use is outside the grant |
| cc-by-nc-sa-4.0 | 6 | 0.3% | Outside the grant, and adaptations carry ShareAlike |
| No licence field | 5 | 0.25% | Unanswered. Blocked until the publisher answers |
Non-commercial rows, and the on-premise inversion
13 of those 2,000 rows carry a non-commercial licence, 7 cc-by-nc-4.0 and 6 cc-by-nc-sa-4.0. That is 0.65 percent, a small share of the wrong kind.
The reason sits in the licence text. CC BY 4.0 Section 3(a) conditions its obligations on Sharing the Licensed Material, including in modified form, so a fine-tune that never leaves your perimeter does not trigger the attribution machinery most teams worry about. A NonCommercial term is different in kind: it restricts the purpose of the exercise rather than the act of redistribution, so it reaches a bank or a pharma manufacturer running a policy on its own line whether or not a byte leaves the building.
That inverts where the control goes. Attribution problems can wait for a release review; a NonCommercial row cannot, because on-premise there is no release to review. Segregate those rows at ingest. The facet query is one call per variant.
# both non-commercial variants, stacked filters, one call each curl -s "https://huggingface.co/api/datasets?filter=LeRobot&filter=license:cc-by-nc-4.0&limit=100" curl -s "https://huggingface.co/api/datasets?filter=LeRobot&filter=license:cc-by-nc-sa-4.0&limit=100"
The other direction is the one on-premise teams miss. The same default that mislabels other people's data publishes and permissively licenses yours. DatasetRecordConfig.push_to_hub defaults to True, the record script passes no licence, and the card that lands reads apache-2.0. An operator recording a shift of cell footage on a defence supplier's line has, by walking away, published it under a grant that includes the Apache 2.0 Section 3 patent licence. No CLI flag changes the licence. One flag stops the publish.
Treat the licence on data you publish as a decision, with a value written down.
from lerobot.datasets.lerobot_dataset import LeRobotDataset
dataset = LeRobotDataset("your-org/cell-4-pick-place", root="/data/robot/cell-4")
dataset.push_to_hub(
license="cc-by-nc-4.0", # or "other" plus license_name and license_link on the card
private=True,
tags=["internal", "cell-4"],
push_videos=False,
)Keeping the footage on the machine that recorded it is a separate control, worked through in where to put cameras for robot imitation learning. On-premise, no supplier stands behind the corpus, so no indemnity absorbs a provenance defect, and your own episodes are the only rows whose terms you get to write, which is priced in teleoperation versus simulation versus human video.
What CC BY 4.0 obliges you to carry that an Apache tag does not surface
When the upstream says CC BY 4.0 and the mirror says apache-2.0, the swap is not cosmetic: the two licences attach different machinery.
Section 3(a)(1)(A) requires retaining, where the licensor supplied them, five things: identification of the creators, a copyright notice, a notice referring to the Public License, a notice referring to the disclaimer of warranties, and a URI or hyperlink to the licensed material where reasonably practicable. Section 3(a)(1)(B) requires indicating if you modified the material and retaining an indication of previous modifications, and Section 3(a)(1)(C) requires indicating that the material is licensed under the Public License and including its text or a link.
Read 3(a)(1)(B) against a mirror. A format conversion that renumbers episodes is a modification, and the cards we opened record none of it: they render - **Homepage:** [More Information Needed] and - **Paper:** [More Information Needed] above - **License:** apache-2.0. The episode counts do not match upstream either: 92,233 for the DROID conversion against the paper's 76,000 trajectories. Transformations, not copies, and the card does not say so.
Further constraints, none of which an Apache tag hints at. Section 3(a)(4) says the licence you apply to shared adapted material must not prevent recipients from complying with the Public License, and Section 2(a)(5)(B) forbids additional terms that restrict the licensed rights. Section 2(b)(2) states that patent and trademark rights are not licensed under CC BY 4.0 at all, while Apache 2.0 Section 3 does grant a patent licence. Section 6(a) terminates your rights on non-compliance, and Section 6(b)(1) reinstates them if the violation is cured within 30 days of your discovery of it.
Apache 2.0 gives a corpus reviewer none of this. Its Section 4 is drafted around Source form, Object form, Derivative Works and a NOTICE text file, concepts written for code. An Apache tag on a corpus of robot episodes produces no attribution string a reviewer can carry forward, which is why a wrong tag is worse than a missing one: it ends the enquiry instead of prompting it. What survives a procurement review is a card that carries the upstream term and points at where it was stated.
--- license: cc-by-4.0 license_link: LICENSE source_datasets: - BridgeData V2 task_categories: - robotics tags: - LeRobot - rlds - openx ---
license_link accepts LICENSE or LICENSE.md inside the repository, or a URL, so the LICENSE file can carry the upstream statement verbatim. Where no standard identifier fits, other plus a license_name does the same job. Above the open-licence layer sits the contractual one, covering brokered data and scraping terms: data privacy and AI training restrictions.
A model card licence and a dataset card licence are two separate reviews
The overlap between a weights review and a data review is smaller than teams assume. The weights review is messy on its own terms: Apache 2.0 code on top of bespoke checkpoint licences, and at least one widely used checkpoint whose model card and repository README disagree. That is the review we run in the VLA model comparison.
A dataset review reads five artefacts: the Hub card front matter, a LICENSE file that may not exist inside the dataset repository, the upstream project page, the upstream code repository, and the paper. Three of those five never appear in a model card review, and for DROID the only statement of terms sits in the document a card review never opens.
Clearing a checkpoint clears nothing about the corpus it was trained on, and the reverse holds too. Run them as two rows on one page, each with its own evidence URL, reviewer and date. The quiet failure is a reviewer pattern-matching on apache-2.0 and writing a wrong fact into the approval record.
The provenance row to write before the first epoch
The training-run manifest already has a place for this. We ship one with a licence field per data source in does fine-tuning make you a provider under the EU AI Act, and no corpus enters the mix without it populated. Upstream of that belongs a dataset-level row recording where the value came from.
Pinning makes the row durable. A Hub card is mutable, the tag is not versioned with the data, and a stale cache can hand you a copy nobody reviewed, the same confusion behind the silent failures in VLA fine-tuning that returns a 0 percent success rate. The reviewed tag and the trained-on tag match only if you record the sha and train against it. Leave --dataset.root off: a concrete local tree loads from disk and the pin never reaches the Hub.
lerobot-train \ --dataset.repo_id=IPEC-COMMUNITY/bridge_orig_lerobot \ --dataset.revision=0e9d76d07e9df3ea3eba257b2520d4913833fad2 \ --policy.type=smolvla
Filling the row does not require pulling terabytes: the card alone answers the tag question.
hf download IPEC-COMMUNITY/bridge_orig_lerobot README.md \ --repo-type dataset \ --local-dir ./probe head -3 ./probe/README.md # --- # license: apache-2.0 # task_categories:
If you control the mirror, correct the card rather than annotating around it. huggingface_hub.metadata_update takes repo_type="dataset" and needs overwrite=True to change an existing field, and create_pr=True leaves a reviewable change instead of a silent one.
This week, run the audit over the corpora already in your training mix and open the upstream page for every row that reads apache-2.0. The ones that are not fine will be the ones nobody looked at, because the tag looked settled. More in our physical AI pillar.
| Field | Example | Where you get it |
|---|---|---|
| Mirror repo id | IPEC-COMMUNITY/bridge_orig_lerobot | The training config |
| Pinned revision | 0e9d76d07e9df3ea3eba257b2520d4913833fad2 | GET /api/datasets/{id}, field sha |
| Declared tag | apache-2.0 | README front matter on the pinned revision |
| Upstream project | BridgeData V2 | The card, the paper, or your own search |
| Upstream statement | All data is provided under the Creative Commons Attribution 4.0 International License | Project page, quoted verbatim |
| Conflict status | Tag contradicts upstream, referred to counsel | Your review |
| Reviewer and date | Named person, 2026.08.25 | Your review |
FAQ
Quick answers to the questions this post tends to raise.



