Skip to main content

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, empty feature_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 to feature_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)

Source distribution for labelpull 0.1.1
File Size Uploaded
labelpull-0.1.1.tar.gz 12.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for labelpull 0.1.1
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page