NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI
Official Python package for working with the Roboflow API
Last release 2 days ago
02 Oct 2026
Ships fairly regularly
a new release about every 2 weeks
Nearly every release is documented
notes for 58 of the last 60 stable releases
1 version withdrawn
withdrawn after publishing
6 years old
154 releases · first in 2020
One column per quarter.
[ar-api] Honor CLI project creation credentials (VID-33) by @digaobarbosa in #536
Full Changelog: v1.6.0...v1.6.1
Project.upload_video
(#535). Upload original
MP4/MOV bytes with batch, tags, metadata, and split; read processing state
with get_video_upload_status or use bounded polling with
wait_for_video_upload / upload_video(..., wait=True). Use the final
uploaded response's videoId: deduplication can change the canonical
Source ID and return resolvedBatch: null. See the
public upload example.Let callers keep an annotated image out of the Dataset by @iurisilvio in #531
action-recognition as a project type by @digaobarbosa in #532ROBOFLOW_REGION, auth login --region, auth set-region by @imbgar-roboflow in #513See CHANGELOG.md for details.
Full Changelog: v1.5.1...v1.6.0
ROBOFLOW_REGION=us|eu (case-insensitive) selects the platform; an
environment value takes precedence over the saved region.roboflow auth login --region eu authenticates against the EU
data-residency platform and records the credentials' region.roboflow auth set-region <us|eu> saves the region; roboflow auth status
reports the region and environment.API_URL still take precedence over the
region. Hosted semantic segmentation has no EU deployment and raises an
error in the EU region instead of sending images to the US.project create --type action-recognition in the CLI
(#532). Requires a
Roboflow platform release that accepts the type; older releases answer
HTTP 422 and the CLI adds a hint.Version.create_training(model_type="cosmos3-edge", ...) ensures the
video-coco export and returns a Training handle. Version.train() is
unchanged.add_to_dataset on Project.single_upload / Project.save_annotation
(#531). Pass
False to store an annotation without moving the image out of its batch
into the Dataset. The default (None) keeps the API's current behavior.Compare model evaluations in the CLI with roboflow eval compare by @leeclemnet in #529
roboflow eval compare by @leeclemnet in #529Full Changelog: v1.5.0...v1.5.1
Workspace.compare_model_evaluations(project, version, frontier_metric=None)
— compare test-set accuracy and median latency, including Pareto frontier
membership and reasons models are excluded.roboflow --workspace <workspace> eval compare --project <project> --version <N>
— display the comparison as a table; use --json for the public API response.
Use --frontier-metric to choose the metric for frontier membership.roboflow eval commands now return exit code 2 for HTTP 401/403
access errors (previously 1).Add Batch Processing CLI commands by @stellasphere in #518
Full Changelog: v1.4.2...v1.5.0
Workspace.autolabel_models() — list the foundation-model catalog
(gpt-6-astra-boxes, sam3-rle, gemini-boxes, ...) with availability,
guidance and credits per image.Project.autolabel_preview(model, image, ontology=...) — free single-image
preview to compare models before starting a job. image accepts an HTTPS
URL, a local file path or a base64 string.Project.autolabel(batch_id, model, model_type="foundational" | "roboflow", ...)
— start a job over a batch; returns {jobId, annotationJobId}. The
ontology is keyed by prompt ({"kitten": "cat", "tabby": "cat"}), so
several prompts can share one output class. preserve_existing_annotations=True
keeps annotations already on the images (the server default replaces them).Project.autolabel_job(job_id) / Workspace.autolabel_job(job_id) — poll
per-subjob progress.roboflow autolabel models | preview | start | job CLI commands.
start --preserve-existing mirrors the SDK flag; job -p ws/project
resolves the workspace the same way start does.pip install "roboflow[heic]"
installs pillow-heif>=1.7.0, and import roboflow registers its Pillow
opener when it is installed. The default install no longer depends on
pi-heif, which is discontinued upstream: its final release, 1.4.0, bundles
libheif 1.23.0, which is affected by the security advisories fixed in libheif
1.23.2 and 1.23.3 (including CVE-2026-84383). roboflow no longer registers
pi-heif even when it is still installed.
Project.check_valid_image() handle HEIC without the extra.
Decoding a local HEIC file, for example with model.predict("photo.heic"),
needs it.feat: annotation-overwrite parameter on upload_dataset and the CLI by @tonylampada in #524
Full Changelog: v1.4.1...v1.4.2
Add custom train-recipe support (describe schema/template, train_recipe on create_training, CLI) by @leeclemnet in #510
Full Changelog: v1.4.0...v1.4.1
Version.describe_train_recipe(model_type) — fetch the tunable
hyperparameter schema, allowed online augmentation/preprocessing steps,
and a ready-to-edit recipe template for a model type.train_recipe on Version.create_training(...) —
pass an edited describe_train_recipe template for custom
hyperparameters/online augmentation (the server dense-fills omitted
defaults). A top-level epochs is folded into the recipe's
hyperparameters (the server resolves recipe epochs ahead of the body
value). train_recipe requires model_type — recipes are minted per
model type, and without one the platform would train the project's
default architecture.roboflow train recipe -p <project> -v <N> -m <model_type> — print the
recipe schema and template as JSON.roboflow train start --train-recipe '<json>' — create the training
through the v2 API and print the new trainingId. Accepts inline JSON
or a curl-style file reference (--train-recipe @train_recipe.json).Support deployment of RFDETRKeypointPreview weights by @sergii-bond in #496
Full Changelog: v1.3.13...v1.4.0
A dataset version can now own many trainings, and a training can produce many models (e.g. a NAS sweep). New object types expose this:
SDK (roboflow/core/training.py, roboflow/core/version.py):
Version.trainings() — list the version's training runs as Training objects.Version.models() — every trained model for the version (the union across its
trainings), as TrainedModel objects. This is now the canonical way to get a
version's models.Version.create_training(speed=, model_type=, checkpoint=, epochs=) — launch a
run without blocking, returning a Training.Training — .models, .refresh(), .cancel(), .stop(), plus
.training_id / .status / .model_type.TrainedModel — .predict(), .predict_video(), .download(), plus
.model_id / .model_type / .metrics. A TrainedModel does everything the
old version.model could; you just reach it through version.models().Adapters (roboflow/adapters/rfapi.py): v2 trainings endpoints —
list_trainings_for_version, get_training, create_training_v2,
cancel_training_v2, stop_training_v2, get_model_weights_url.
workspace.update_image_metadata() and workspace.batch_update_image_metadata()
(plus a project.update_image_metadata() convenience alias) — public SDK
wrappers for updating metadata and tags on existing images, previously only
reachable via the internal rfapi adapter or the CLI. The batch method
accepts wait=True to poll the async task until completion and return
per-image results.checkpoint_best_ema.pth):
upload_model detects them and rebuilds a deploy-ready bundle via rf-detr's
export_for_roboflow (requires rfdetr>=1.8.0)
(#488)version.model (the singular attribute) is deprecated and emits a
DeprecationWarning. It cannot represent a version with multiple models;
use version.models() instead.feat(cli): adapt raw rf-detr PyTorch-Lightning checkpoints on upload by @leeclemnet in #488
Full Changelog: v1.3.12...v1.3.13
Relax idna pin from ==3.7 to >=3.7 by @iurisilvio in #504
Full Changelog: v1.3.11...v1.3.12
Adds a roboflow api-key CLI command group and SDK methods to create, list, get, update, protect, disable, and revoke workspace API keys, including sco
Adds a roboflow api-key CLI command group and SDK methods to create, list, get, update, protect, disable, and revoke workspace API keys, including scoped keys, folder restrictions, and custom metadata (scoping and metadata require the Advanced API Keys plan feature).
roboflow api-keylist · get · create · update · protect · disable · revoke · publishable--scope (repeatable) / --no-scopes / --full-access; --folder; metadata via --metadata / --clear-metadata--json structured output and actionable error messages on 403/404roboflow.adapters.rfapicreate_api_key, list_api_keys, get_api_key, update_api_key, revoke_api_key, get_publishable_keynumpy<2.5 to unblock the mypy typecheck.Full changelog: v1.3.10...v1.3.11
roboflow api-key CLI command group and SDK methods to create, list, get,
update, protect, and revoke workspace API keys — including scoped keys, folder
restrictions, and custom metadata (scoping/metadata require the Advanced API
Keys plan feature).fix(cli): scope 'image search -p' to the project by @digaobarbosa in #486
Full Changelog: v1.3.9...v1.3.10
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.3.9...v1.3.10
version.deploy() and workspace.deploy_model()Wraps the public /{workspace}/model-evals REST surface so users can read evaluation results — mAP, confidence sweep, per-class performance, confusion
Wraps the public /{workspace}/model-evals REST surface so users can read evaluation results — mAP, confidence sweep, per-class performance, confusion matrix, vector clusters, per-image stats, recommendations — from Python and from the CLI without hitting the API directly.
Workspace.evals(project=None, version=None, model=None, status=None, limit=None) — list evals as ModelEval instances pre-populated with metadata from the list response.Workspace.eval(eval_id) — fetch a single eval (returns a ModelEval with .summary populated when status is done).ModelEval.refresh() — re-fetch the eval header.ModelEval.map_results(), .confidence_sweep(), .performance_by_class(split=None), .confusion_matrix(split=None, confidence=None), .vector_analysis(confidence=None), .image_predictions(split=None, confidence=None, limit=None, offset=None), .recommendations() — one method per panel; each returns the raw JSON dict.roboflow eval list [--project P] [--version V] [--model M] [--status S] [--limit N]roboflow eval get <eval_id>roboflow eval map-results <eval_id>roboflow eval confidence-sweep <eval_id>roboflow eval performance-by-class <eval_id> [--split S]roboflow eval confusion-matrix <eval_id> [--split S] [--confidence N]roboflow eval vector-analysis <eval_id> [--confidence N]roboflow eval image-predictions <eval_id> [--split S] [--confidence N] [--limit N] [--offset N]roboflow eval recommendations <eval_id>Exit codes are stable per error class so shell scripts and AI agents can react without parsing message strings: 3 for model_eval_not_found (404), 4 for model_eval_not_done (409), 5 for invalid_split / invalid_confidence (400). Every command supports --json for structured output.
roboflow.adapters.rfapi)list_model_evals, get_model_eval, get_model_eval_map_results, get_model_eval_confidence_sweep, get_model_eval_performance_by_class, get_model_eval_confusion_matrix, get_model_eval_vector_analysis, get_model_eval_image_predictions, get_model_eval_recommendations.ModelEvalNotFoundError, ModelEvalNotDoneError, InvalidSplitError, InvalidConfidenceError (all subclasses of RoboflowError) so callers can distinguish "eval doesn't exist" from "eval still running" from "bad argument" without parsing strings.The endpoints require the model-eval:read scope.
args is a plain dict (e.g. EMA checkpoints) when extracting class names, instead of raising TypeError from vars().typer<0.26 and declare click explicitly: typer 0.26 vendors its own click and drops the external dependency, which broke the CLI and its type checks.Full Changelog: v1.3.8...v1.3.9
Wraps the public /{workspace}/model-evals REST surface
(roboflow/roboflow#11636)
so users can read evaluation results — mAP, confidence sweep, per-class
performance, confusion matrix, vector clusters, per-image stats,
recommendations — from Python and from the CLI without hitting the API
directly. Companion docs:
roboflow-dev-reference#18.
SDK (roboflow/core/model_eval.py):
Workspace.evals(project=None, version=None, model=None, status=None, limit=None) — list evals as ModelEval instances pre-populated with metadata from the list response.Workspace.eval(eval_id) — fetch a single eval (returns a ModelEval with .summary populated when status is done).ModelEval.refresh() — re-fetch the eval header.ModelEval.map_results(), .confidence_sweep(), .performance_by_class(split=None), .confusion_matrix(split=None, confidence=None), .vector_analysis(confidence=None), .image_predictions(split=None, confidence=None, limit=None, offset=None), .recommendations() — one method per panel; each returns the raw JSON dict.CLI (roboflow/cli/handlers/eval.py):
roboflow eval list [--project P] [--version V] [--model M] [--status S] [--limit N]roboflow eval get <eval_id>roboflow eval map-results <eval_id>roboflow eval confidence-sweep <eval_id>roboflow eval performance-by-class <eval_id> [--split S]roboflow eval confusion-matrix <eval_id> [--split S] [--confidence N]roboflow eval vector-analysis <eval_id> [--confidence N]roboflow eval image-predictions <eval_id> [--split S] [--confidence N] [--limit N] [--offset N]roboflow eval recommendations <eval_id>Exit codes are stable per error class so shell scripts and AI agents can
react without parsing message strings: 3 for model_eval_not_found
(404), 4 for model_eval_not_done (409), 5 for invalid_split /
invalid_confidence (400). Every command supports --json for
structured output.
Low-level (roboflow.adapters.rfapi):
list_model_evals, get_model_eval, get_model_eval_map_results, get_model_eval_confidence_sweep, get_model_eval_performance_by_class, get_model_eval_confusion_matrix, get_model_eval_vector_analysis, get_model_eval_image_predictions, get_model_eval_recommendations.ModelEvalNotFoundError, ModelEvalNotDoneError, InvalidSplitError, InvalidConfidenceError (all subclasses of RoboflowError) so callers can distinguish "eval doesn't exist" from "eval still running" from "bad argument" without parsing strings.The endpoints require the model-eval:read scope. The base URL is
configurable via API_URL (set to https://localapi.roboflow.one to
test against a local API server).
args is a plain dict (e.g. EMA checkpoints) when extracting class names, instead of raising TypeError from vars().typer<0.26 and declare click explicitly: typer 0.26 vendors its own click and drops the external dependency, which broke the CLI and its type checks.Adds Python SDK and CLI bindings for the external Deployments / Device Management API (shipped in #469 ). 1:1 with the documented public routes. PATCH
Adds Python SDK and CLI bindings for the external Deployments / Device Management API (shipped in #469). 1:1 with the documented public routes. PATCH /config, stream commands, device delete, and fleet-groups CRUD are intentionally out of scope.
Workspace.devices() — list all devices in the workspace.Workspace.device(id) — fetch a single device by id.Workspace.create_device(...) — register a new device.Device — handle exposing config(), config_history(), streams(), stream(id), logs(...), telemetry(...), events(...), refresh().import roboflow
rf = roboflow.Roboflow(api_key="...")
ws = rf.workspace()
for d in ws.devices():
print(d.id, d.name, d.status)
device = ws.device("dev_abc123")
print(device.telemetry(time_period="1h"))
Device.config()may includeenvironment_variablesand integration credentials. Treat the returned payload as sensitive; the CLI prints a stderr advisory in interactive mode.
roboflow device list [--json]
roboflow device get <id> [--json]
roboflow device create --name <name> ... [--json]
roboflow device config <id> [--json]
roboflow device config-history <id> [--json]
roboflow device streams <id> [--json]
roboflow device stream <id> <stream-id> [--json]
roboflow device logs <id> [--service ...] [--severity ...] [--json]
roboflow device telemetry <id> [--time-period 1h] [--json]
roboflow device events <id> [--entity-type stream] [--json]
Every command supports --json for structured output and emits actionable hints with stable exit codes (0 success, 1 error, 2 auth, 3 not-found). Rate-limited responses (429) include backoff hints.
roboflow.adapters.devicesapi)New typed exceptions: DeviceBadRequestError (400), DeviceAuthError (401/403), DeviceNotFoundError (404), DeviceRateLimitedError (429), DeviceApiError (5xx). HTTP layer covers all 10 documented routes.
Purely additive. The new endpoints require the following scopes:
| Action | Required scope |
|---|---|
device list / device get / device config / device config-history / device streams / device stream / device logs / device telemetry / device events |
device:read |
device create |
device:update |
Full diff: v1.3.7...v1.3.8
Mirrors the soft-delete and Trash features added to the Roboflow web app (roboflow/roboflow#11131). Deleting a project, version, or workflow now moves
Mirrors the soft-delete and Trash features added to the Roboflow web app (roboflow/roboflow#11131). Deleting a project, version, or workflow now moves it to Trash with a 30-day retention window (and cancels any in-flight training jobs); items can be restored within that window. Companion docs: roboflow-dev-reference#5.
Project.delete() — soft-deletes the project. Returns the server response.Project.restore() — looks the project up in the workspace Trash by slug and restores it; raises RuntimeError if not currently in Trash.Version.delete() / Version.restore() — same shape on a version handle.Workspace.trash() — lists everything in a workspace's Trash, grouped by projects / versions / workflows. Returns the raw API payload (so you have access to parentId, parentUrl, scheduledCleanupAt, etc.).Workspace.restore_from_trash(item_type, item_id, parent_id=None) — restores by id when you don't have a live SDK handle. item_type is "project", "version", or "workflow"; parent_id is required when restoring a version.import roboflow
rf = roboflow.Roboflow(api_key="...")
ws = rf.workspace()
# Discover what's in Trash
trash = ws.trash()
for item in trash["items"]:
print(item["type"], item["name"], "cleanup:", item["scheduledCleanupAt"])
# Restore a project you don't have a handle for
project_in_trash = trash["sections"]["projects"][0]
ws.restore_from_trash("project", project_in_trash["id"])
roboflow project delete <slug> [--yes] [--json]
roboflow project restore <slug> [--yes] [--json]
roboflow version delete <slug>/<v> [--yes] [--json]
roboflow version restore <slug>/<v> [--yes] [--json]
roboflow workflow delete <url> [--yes] [--json]
roboflow workflow restore <url> [--yes] [--json]
roboflow trash list [--json]
Destructive commands prompt for confirmation interactively; pass --yes / -y for scripted use. Every command supports --json for structured output and emits actionable hints with stable exit codes (0 success, 1 error, 2 auth, 3 not-found).
roboflow.adapters.rfapi)New helpers: delete_project, delete_version, delete_workflow, list_trash, restore_trash_item. RoboflowError messages now extract the error field from JSON response bodies (e.g. "Not authorized to view trash") instead of returning raw response text.
Emptying Trash and immediately deleting a single Trash item destroy data irrecoverably and live only in the Roboflow app's Trash view, which has an explicit confirmation dialog. Items left in Trash are cleaned up automatically after 30 days. Guard tests in this release ensure those actions stay off the SDK/CLI surface going forward.
Workspace.create_workflow() and roboflow workflow create --definition now auto-wrap bare workflow definitions in {"specification": ...} before POSTing to the backend, matching what the web app does (#460). Previously, the user-facing flat shape ({version, inputs, steps, outputs}) — the shape published in the Workflows docs — was sent verbatim, so executing the resulting workflow returned HTTP 502 with MalformedWorkflowResponseError: Workflow specification not found in Roboflow API response.
Workflows already wrapped (top-level specification key) are passed through unchanged. Non-workflow dicts and non-JSON strings are also passed through verbatim so custom payloads aren't second-guessed.
Workflows that were stored with the bare shape before this fix will still 502 until re-saved. Run
roboflow workflow update <url> --definition <file>once per affected workflow to migrate.
upload_image no longer re-encodes images client-side (#464) — uploads original bytes instead of round-tripping through JPEG.Purely additive on the public API surface. The new endpoints require project:update, version:update, or workflow:update scopes — most existing keys already have these.
| Action | Required scope |
|---|---|
project delete / project restore |
project:update |
version delete / version restore |
version:update |
workflow delete / workflow restore |
workflow:update |
trash list |
project:read |
Full diff: https://github.com/roboflow/roboflow-python/compare/v1.3.6...v1.3.7
Mirrors the soft-delete and Trash features added to the Roboflow web app (roboflow/roboflow#11131). Deleting a project, version, or workflow now moves it to Trash with a 30-day retention window (and cancels any in-flight training jobs); items can be restored within that window. Companion docs: roboflow-dev-reference#5.
SDK (roboflow/):
Project.delete() / Project.restore() — soft-delete and restore by slug.Version.delete() / Version.restore() — same shape on a version handle.Workspace.trash() — list everything currently in a workspace's Trash, grouped by projects / versions / workflows.Workspace.restore_from_trash(item_type, item_id, parent_id=None) — restore an item by id when you don't have a live SDK handle (or for workflows, which don't have a first-class object yet).CLI (roboflow/cli/):
roboflow project delete / roboflow project restoreroboflow version delete / roboflow version restoreroboflow workflow delete / roboflow workflow restoreroboflow trash listDestructive commands prompt for confirmation interactively and accept
--yes / -y for scripted use. Every command supports --json for
structured output and emits actionable error hints with stable exit codes.
Low-level (roboflow.adapters.rfapi):
delete_project, delete_version, delete_workflow, list_trash, restore_trash_item.RoboflowError messages now extract the error field from JSON response bodies (e.g. "Not authorized to view trash") instead of the raw response text.Permanent deletion is intentionally web-UI-only. Emptying Trash or immediately deleting a single Trash item destroys data irrecoverably, so those actions are not exposed on the SDK or CLI — they live only in the Roboflow app's Trash view, which has an explicit confirmation dialog. Items left in Trash are cleaned up automatically after 30 days.
Workspace.create_workflow() and roboflow workflow create --definition
auto-wrap bare workflow definitions in {"specification": ...} before
POSTing to the backend, matching what the web app does
(#460). Previously,
the user-facing flat shape ({version, inputs, steps, outputs}) was sent
verbatim, so POST /infer/workflows/... against the resulting workflow
returned HTTP 502 with MalformedWorkflowResponseError: Workflow specification not found in Roboflow API response.
Workflows already wrapped (top-level specification key) are passed
through unchanged. Non-workflow dicts and non-JSON strings are also
passed through verbatim so custom payloads aren't second-guessed.
Note: workflows that were stored with the bare shape before this fix will still 502 until re-saved. Run
roboflow workflow update <url> --definition <file>once per affected workflow to migrate.
upload_image now uploads original image bytes instead of re-encoding to
JPEG client-side (#464).
Purely additive on the public API surface. The new endpoints require
project:update, version:update, or workflow:update scopes — most
existing keys already have these.
fix: upload original image bytes instead of re-encoding to JPEG (ENT-1169) by @rvirani1 in #464
Full Changelog: v1.3.5...v1.3.6
Remove direct publishing via twine (ENT-1128) by @rvirani1 in https://github.com/roboflow/roboflow-python/pull/459
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.3.3...v1.3.5
New SDK support for the Vision Events API: write single/batch events, query with pagination, list use cases, and upload images.
Vision Events SDK & CLI (#451)
roboflow vision-events CLI command group with subcommands: write, write-batch, query, use-cases, upload-image.roboflow-slim package (#451)
roboflow-slim install option for environments where PIL/OpenCV aren't needed (e.g. event ingestion pipelines, serverless functions).Default inference URLs updated to Serverless V2 (#377)
serverless.roboflow.com instead of the legacy detect.roboflow.com / outline.roboflow.com endpoints.'str' object has no attribute 'get' traceback. (#450)Nothing published for this version
This release rewrites the Roboflow CLI from the ground up to serve as the canonical machine interface for the Roboflow platform. Every command now sup
This release rewrites the Roboflow CLI from the ground up to serve as the canonical machine interface for the Roboflow platform. Every command now supports --json for structured output, follows a consistent noun verb pattern, and provides actionable error messages to make Roboflow accessible to coding agents, CI/CD pipelines, and automation workflows.
🏗️ Modular CLI architecture — The monolithic CLI has been decomposed into 18 handler modules organized by resource (project, version, image, model, workspace, etc.), each with a clean noun-verb pattern. (#445)
📡 REST API feature parity — 22 new API adapter functions and corresponding CLI commands for folders, annotation batches/jobs, workflows, workspace stats, version creation, video status, and universe search. (#446)
⚡ Typer framework migration — Migrated from argparse to typer for Rich-formatted help, built-in shell completion, type-safe parameters, and consistency with the Roboflow Inference CLI. (#447)
| Group | Commands |
|---|---|
annotation batch |
list, get |
annotation job |
list, get, create |
folder |
list, create, delete |
workflow |
list, get, create, update, version-list, fork |
workspace stats |
team, usage, plan |
version create |
Create new dataset versions from CLI |
video status |
Check async video inference job status |
universe search |
Search public datasets and models |
model infer |
Run inference (canonical form of infer) |
image search |
Unified workspace/project search with optional -p flag |
completion |
bash, zsh, fish — shell completion scripts |
--json everywhere — Every command supports --json for structured output with a stable schema{"error": {"message": "...", "hint": "..."}} on stderr with exit codes (0=success, 1=error, 2=auth, 3=not found)roboflow --help shows all commands as noun verb in a single viewroboflow completion bash/zsh/fish generates completion scriptsWorkspace.list_folders(), create_folder(), delete_folder()Workspace.get_team_stats(), get_usage_stats(), get_plan_info()Project.list_batches(), get_batch(), list_jobs(), get_job(), create_job()Project.list_workflows(), get_workflow(), create_workflow(), update_workflow()Workspace.delete_image() (#442)typer>=0.12.0 added as a dependency (replaces argparse for CLI)All legacy CLI commands and flags continue to work. The old roboflow upload, roboflow download, roboflow login forms are preserved as hidden aliases. Scripts importing from roboflow.roboflowpy remain functional.
Project.delete_images() method (#424)Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.2.16...v1.3.1
At the workspace level you can now search and delete images.
At the workspace level you can now search and delete images.
Sample code using both:
"""Delete all orphan images matching a workspace-level search query.
Usage:
python tests/manual/demo_search_delete.py
"""
from roboflow import Roboflow
QUERY = "project:false"
PAGE_SIZE = 100
DELETE_BATCH_SIZE = 1000
DRY_RUN = False # set to False to actually delete
WORKSPACE_SLUG = "workspace"
def main():
rf = Roboflow()
workspace = rf.workspace(WORKSPACE_SLUG)
print(f"Workspace: {workspace.url}")
print(f"Query: {QUERY}")
print(f"Dry run: {DRY_RUN}")
print()
# Collect all matching image IDs.
# When deleting (not dry run), skip continuation tokens because deleted
# images shift the result set — always re-search from page 1.
all_ids = []
token = None
while True:
page = workspace.search(
QUERY,
page_size=PAGE_SIZE,
fields=["filename"],
continuation_token=token,
)
results = page.get("results", [])
if not results:
break
total = page.get("total", "?")
all_ids.extend(img["id"] for img in results)
print(f"Found {len(all_ids)}/{total} images so far...")
token = page.get("continuationToken")
if not token:
break
print(f"\nTotal images matching '{QUERY}': {len(all_ids)}")
if not all_ids:
print("Nothing to delete.")
return
if DRY_RUN:
print("\n[DRY RUN] Would delete the above images. Set DRY_RUN=False to proceed.")
return
for i in range(0, len(all_ids), DELETE_BATCH_SIZE):
batch = all_ids[i : i + DELETE_BATCH_SIZE]
print(f"Deleting batch {i // DELETE_BATCH_SIZE + 1} ({len(batch)} images)...")
result = workspace.delete_images(batch)
print(f" deleted={result.get('deletedSources')}, skipped={result.get('skippedSources')}")
print(f"\nDone. Deleted {len(all_ids)} images.")
if __name__ == "__main__":
main()
We now make it available to the python sdk to upload metadata when starting upload
We now make it available to the python sdk to upload metadata when starting upload
We provide a new method to export images and annotations based on search queries. It replicates the Asset Library Download functionality on the CLI.
We provide a new method to export images and annotations based on search queries. It replicates the Asset Library Download functionality on the CLI.
Includes model upload for new rf-detr models. pi_heif discontinued Python3.9 support, so this is handled in the release as well.
Includes model upload for new rf-detr models. pi_heif discontinued Python3.9 support, so this is handled in the release as well.
Users can now upload yolo26 models from ultralytics 8.4.1 or higher
Users can now upload yolo26 models from ultralytics 8.4.1 or higher
adds curlable script to sign urls to images in s3 buckets by @tonylampada in https://github.com/roboflow/roboflow-python/pull/419
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.2.10...v1.2.11
Added Confidence Argument to keypoint detection model by @Greenstan in https://github.com/roboflow/roboflow-python/pull/354
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.2.9...v1.2.10
fix is_prediction function call by @sberan in https://github.com/roboflow/roboflow-python/pull/413
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.2.8...v1.2.9
Add are_predictions flag to dataset upload by @sberan in https://github.com/roboflow/roboflow-python/pull/412
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.2.7...v1.2.8
configuring devcontainer to call localhost by @digaobarbosa in https://github.com/roboflow/roboflow-python/pull/409
Project object local instead of calling API after create project by @iurisilvio in https://github.com/roboflow/roboflow-python/pull/411Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.2.6...v1.2.7
Fix train-over-api devx by @tonylampada in https://github.com/roboflow/roboflow-python/pull/408
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.2.5...v1.2.6
Add function to debug train api by @tonylampada in https://github.com/roboflow/roboflow-python/pull/400
annotation_job and annotation_job_id by @iurisilvio in https://github.com/roboflow/roboflow-python/pull/406Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.2.4...v1.2.5
model_type parameter by @digaobarbosa in https://github.com/roboflow/roboflow-python/pull/401
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.2.3...v1.2.4
Increase supported model types by @probicheaux in https://github.com/roboflow/roboflow-python/pull/397
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.2.1...v1.2.3
Add the ability to upload new rf-detr sizes (small, medium, nano)
Add the ability to upload new rf-detr sizes (small, medium, nano)
Support YAML dict labelmaps by @ford-downer-robo in https://github.com/roboflow/roboflow-python/pull/395
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.2.0...v1.2.1
Use pillow-avif-plugin for AVIF support and support pillow-heif 1.0 by @iurisilvio in https://github.com/roboflow/roboflow-python/pull/392
pillow-avif-plugin for AVIF support and support pillow-heif 1.0 by @iurisilvio in https://github.com/roboflow/roboflow-python/pull/392Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.1.67...v1.2.0
Fix #390: Lock pillow-hief version to not break AVIF support by @MuhammadHadiofficial in https://github.com/roboflow/roboflow-python/pull/391
pillow-hief version to not break AVIF support by @MuhammadHadiofficial in https://github.com/roboflow/roboflow-python/pull/391Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.1.66...v1.1.67
chore(pre_commit): ⬆ pre_commit autoupdate by @pre-commit-ci in https://github.com/roboflow/roboflow-python/pull/324
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.1.65...v1.1.66
Upgrade devcontainer by @tonylampada in https://github.com/roboflow/roboflow-python/pull/382
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.1.64...v1.1.65
Enhance error handling in model deployment URL retrieval by @lrosemberg in https://github.com/roboflow/roboflow-python/pull/379
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.1.63...v1.1.64
Adds support for yolov7 model upload by @lrosemberg in https://github.com/roboflow/roboflow-python/pull/375
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.1.62...v1.1.63
Normalize Windows style paths to parse folder by @iurisilvio in https://github.com/roboflow/roboflow-python/pull/376
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.1.61...v1.1.62
Publish mkdocs in gh-pages when a new release is created by @lrosemberg in https://github.com/roboflow/roboflow-python/pull/373
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.1.60...v1.1.61
Fix handling of invalid annotation descriptions and add tests to dataset uploads by @shantanubala in https://github.com/roboflow/roboflow-python/pull/
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.1.58...v1.1.60
Support for more image types on upload by @joaomarcoscrs in https://github.com/roboflow/roboflow-python/pull/366
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.1.57...v1.1.58
Adds support for YOLOv12 model upload by @lrosemberg in https://github.com/roboflow/roboflow-python/pull/361
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.1.56...v1.1.57
Add a project method for creating annotation jobs by @shantanubala in https://github.com/roboflow/roboflow-python/pull/363
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.1.55...v1.1.56
Check that responsejson is instance of dict by @stellasphere in https://github.com/roboflow/roboflow-python/pull/342
Full Changelog: https://github.com/roboflow/roboflow-python/compare/1.1.54...v1.1.55
Add support for the Image Details endpoint by @stellasphere in https://github.com/roboflow/roboflow-python/pull/344
download_dataset does not respect ROBOFLOW_API_KEY by @SkalskiP in https://github.com/roboflow/roboflow-python/pull/359Full Changelog: https://github.com/roboflow/roboflow-python/compare/1.1.53...1.1.54
Model processor by @lrosemberg in https://github.com/roboflow/roboflow-python/pull/355
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.1.51...1.1.53
Only stretch image to resize if format is Stretch by @SolomonLake in https://github.com/roboflow/roboflow-python/pull/352
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.1.50...v1.1.51
PaliGemma2 model upload support by @lrosemberg in https://github.com/roboflow/roboflow-python/pull/347
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.1.48...v1.1.50
upload_model command with the following model types:
paligemma2-3b-pt-224paligemma2-3b-pt-448paligemma2-3b-pt-896Add log support for dedicated deployment by @PacificDou in https://github.com/roboflow/roboflow-python/pull/335
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.1.48...v1.1.49
Bump package version by @SolomonLake in https://github.com/roboflow/roboflow-python/pull/331
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.1.47...v1.1.48
Nothing published for this version
fix_box_loss_error by @venkatram-dev in https://github.com/roboflow/roboflow-python/pull/313
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.1.45...v1.1.46
chore(pre_commit): ⬆ pre_commit autoupdate by @pre-commit-ci in https://github.com/roboflow/roboflow-python/pull/310
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.1.44...v1.1.45
Feat: Multi-label support by @balthazur in https://github.com/roboflow/roboflow-python/pull/320
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.1.43...v1.1.44
Fix yolov10 version deploy by @grzegorz-roboflow in https://github.com/roboflow/roboflow-python/pull/319
Full Changelog: https://github.com/roboflow/roboflow-python/compare/v1.1.42...v1.1.43
poll video inference job fix by @PacificDou in https://github.com/roboflow/roboflow-python/pull/317
Your coding agent can read these notes before it upgrades. Set up the MCP server →