For the complete documentation index, see llms.txt. This page is also available as Markdown.

Watch a Folder for New Images

Watch a directory and auto-upload new images to a Roboflow project.

A common ingestion pattern is to drop new images into a directory (a synced cloud folder, a camera's NAS export, an SFTP target) and have them automatically appear in a Roboflow project.

This recipe shows two implementations: a Python script using watchdog (best when you're already running a Python service), and a shell loop using the CLI (best for cron-style automation).

Python: watchdog + SDK

pip install roboflow watchdog
import os
import time
from pathlib import Path

import roboflow
from watchdog.events import FileSystemEventHandler
from watchdog.observers import Observer

WATCH_DIR = Path("./incoming")
PROJECT_ID = "my-detector"
BATCH_NAME = "auto-ingest"

rf = roboflow.Roboflow()
project = rf.workspace().project(PROJECT_ID)


class IngestHandler(FileSystemEventHandler):
    def on_created(self, event):
        if event.is_directory:
            return
        path = Path(event.src_path)
        if path.suffix.lower() not in {".jpg", ".jpeg", ".png"}:
            return
        # Wait briefly so the file is fully written before we read it.
        time.sleep(1)
        try:
            project.upload_image(
                image_path=str(path),
                split="train",
                batch_name=BATCH_NAME,
                num_retry_uploads=3,
            )
            print(f"uploaded {path.name}")
        except Exception as e:
            print(f"failed {path.name}: {e}")


observer = Observer()
observer.schedule(IngestHandler(), str(WATCH_DIR), recursive=True)
observer.start()
try:
    while True:
        time.sleep(60)
except KeyboardInterrupt:
    observer.stop()
observer.join()

What it does:

  • Watches WATCH_DIR for new .jpg/.jpeg/.png files.

  • Uploads each new file to PROJECT_ID under the auto-ingest batch.

  • Retries transient upload failures.

To productionize: run it under systemd or in a Docker container, point logs at your observability stack, and add a deduplication step (Roboflow already deduplicates server-side by SHA-256 since roboflow 1.3.6, so a re-uploaded image is harmless).

Shell: inotifywait + CLI

For macOS, swap inotifywait for fswatch:

Periodic poll (no daemon)

If you can't run a long-lived process, poll on a cron schedule and upload anything that wasn't uploaded last time. The CLI's --json output and stable exit codes make this easy:

Then add to crontab:

Going further

  • Combine with Active Learning to filter out unhelpful frames before they're uploaded.

  • Use Annotation Jobs to auto-assign new uploads to a labeler.

  • Tag uploads (tag_names=...) so you can search them later - see Search Images.

Last updated

Was this helpful?