labelpull
Pull the latest Labelbox annotations into a tidy, ontology-agnostic table.
The Labelbox SDK already exports a project's labels and streams them. What it
doesn't give you is a tabular view of that deeply nested JSON, the correctness
logic to pick the right label when a row was reviewed, or a workflow status that
is always populated. labelpull is exactly that thin layer on top of the SDK.
Quick start
pip install 'labelpull[live]'
export LABELBOX_API_KEY=... # Labelbox → Workspace settings → API keys
labelpull pull <PROJECT_ID> -o labels.csv # <PROJECT_ID> is in your project's URL
You get one row per annotation (any ontology):
global_key,data_row_id,feature_kind,feature_name,value,workflow_status,labeled_by,created_at,parent_feature_id
photo_001.jpg,clz…,label,,,Done,bot@lab.org,2026-06-05T08:00:00Z,
photo_001.jpg,clz…,radio,Species,Ficus insipida,Done,bot@lab.org,2026-06-05T08:00:00Z,
photo_001.jpg,clz…,checklist,Organs,leaf;flower,Done,bot@lab.org,2026-06-05T08:00:00Z,
The first row of each photo (
feature_kind=label, emptyfeature_name) is a marker that the photo was reached and labelled — it carries who/when even when the annotator left it blank, so empty-but-labelled photos still show up. Ignore it if you only want answers: filter tofeature_kind != "label".
Install
pip install labelpull # offline parsing + CLI (no SDK)
pip install 'labelpull[live]' # + the Labelbox SDK, for live pulls from the API
CLI
labelpull pull <PROJECT_ID> -o labels.csv # everything, generic long CSV
labelpull pull <PROJECT_ID> --status Done # only verified rows
labelpull pull <PROJECT_ID> --since 2026-06-01 # only labels created since a date
labelpull pull <PROJECT_ID> --from-export export.ndjson # offline: a UI "Export" file, no API key
--status takes ToLabel | InReview | InRework | Done. Every run prints a
summary (rows, labelled count, feature kinds, latest label timestamp).
If your project is a single-classification task and you want one row per item
instead of the long format, filter the CSV to your feature (e.g. keep
feature_name == "Species"), or write a 10-line Adapter (see below).
Library
import labelpull
rows = list(labelpull.export("proj_id", status="Done")) # live; needs labelpull[live]
# or, offline from a UI export:
# rows = labelpull.read_export_file("export.ndjson")
features = [f for r in rows for f in labelpull.flatten(r, "proj_id")]
labelpull.write_csv("labels.csv", labelpull.GenericAdapter(), features)
print(labelpull.summarize(rows, features))
flatten() handles radio / checklist / text classifications and bbox / polygon /
line / point / mask objects (with nested classifications linked to their parent),
and always selects the most recently created label so a QC-reviewed row reports
the reviewer's answer, not the annotator's.
Custom output shape
GenericAdapter (the default) writes one row per feature. To collapse features
into a project-specific wide table, write an Adapter — given the flattened
FeatureRows, yield your own columns. SpeciesAdapter is a worked example
(it pivots a Taxon radio + Organs checklist into one row per photo):
labelpull pull <PROJECT_ID> --schema species -o taxa.csv
Release files for labelpull 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| labelpull-0.1.1.tar.gz | 12.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| labelpull-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size:22.8 kB
Release files / labelpull-0.1.1.tar.gz
| Download URL | labelpull-0.1.1.tar.gz |
|---|---|
| Size | 12.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e8fb4385a11a64c6610585a11158adf26d69e569df8ec25845f0091ea31f205e
|
|
BLAKE2b-256 checksum How to use checksums |
1e4dab1c075c145fcd7c2f9bc8cd7d92e576652958db2500670d581322d4b122
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 10, 2026.
Transparency logRelease files / labelpull-0.1.1-py3-none-any.whl
| Download URL | labelpull-0.1.1-py3-none-any.whl |
|---|---|
| Size | 10.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0f967abdbebb694a2dbd50df7ce6f0fc6709107a2f051c29583c4bdc5f491840
|
|
BLAKE2b-256 checksum How to use checksums |
e38ce4b48e8fa6dba5ff70af350a9ce6a07ffee56f5a36ee1f6b3286b46bbf5e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 10, 2026.
Transparency log