Skip to content

Repository files navigation

ARGUS — Global Camera Intelligence

Argus is an open-source, real-time interactive map of 229,000+ public traffic and CCTV cameras from government and commercial sources worldwide — highway DOT cameras, city traffic cams, and public webcams, aggregated from open data APIs and rendered on a GPU-accelerated map (with a 3D globe view built in). Dashboard for exploring live camera feeds, HLS video streams, and static snapshot imagery by country, region, or city, backed by a Python scraping pipeline that keeps the dataset current.

It's two independent halves:

  • Frontend (src/) — a React + TypeScript dashboard. Reads a static JSON payload at runtime; it never talks to the scrapers directly.
  • Data pipeline (scripts/) — a Python CLI that scrapes camera metadata from ~10 government/commercial sources into a local SQLite store, then exports it to the JSON payload the frontend reads.

Note: This project already comes with all of the cameras preloaded, so there is no need to scrape unless you want the most up-to-date cameras.

Features

  • 2D map view — thousands of camera dots over a dark MapLibre basemap, rendered with Deck.GL for performance at scale.
  • 3D globe view — the same data on a rotating globe (react-map-gl + MapLibre's native globe projection), toggleable from the HUD.
  • Live feed playback — HLS streams via hls.js where available, falling back to a cache-busted static JPEG poll if the stream fails. A local dev-only proxy (scripts/server.py) resolves CORS and ipcamlive:// streams that a browser can't reach directly.
  • Filters, settings, and a country/sector browser for narrowing down the camera set, plus a "jump to random camera" action.
  • In-app data sync — a Settings-panel button that triggers a scrape and re-export via the local control server, with live progress streamed into the UI.

Showcase

Argus Tactical UIArgus Tactical UI

Quick Start

Prerequisites: Node.js ^20.19.0 || >=22.12.0 (required by Vite 8), Python 3.9+.

Frontend

npm install
npm run dev # Vite dev server, http://localhost:5173

Other frontend commands:

npm run build # tsc -b && vite build
npm run lint # eslint .
npm run preview # preview a production build locally

There is no test suite configured (npm test does not exist).

Data pipeline (from scripts/)

cd scripts
pip install requests
python scraper.py --list # see all plugins
python scraper.py --all # run everything

Camera data lives in a SQLite store (scripts/data/cameras.db) and is exported to public/cameras.geojson plus the three-tier payload the frontend reads at runtime: cameras.core.json (map), cameras.labels.json (names, loaded behind it), and cameras.detail/ (one chunk fetched per camera opened).

Local dev control server (optional — powers the in-app "Data Sync" button)

python scripts/server.py # listens on http://localhost:8787, run alongside `npm run dev`

Configuration

Only the windy plugin needs a key — every other source is keyless. Create .env in the project root:

WINDY_API_KEY=your_key_hereVITE_WINDY_API_KEY=your_key_here

Get a free key at api.windy.com. Both vars must hold the same value — WINDY_API_KEY is used by Python, VITE_WINDY_API_KEY is exposed to the browser by Vite.

Project Structure

Argus/
├── src/
│ ├── App.tsx # Entire UI: HUD, settings, filters, feed panel, both map renderers
│ ├── binWorker.ts # Pixel-binning for the 2D map at low zoom (Web Worker)
│ ├── main.tsx # React entry point
│ └── assets/ # Demo screenshots
├── public/
│ ├── cameras.geojson # Full dataset, one feature per camera (also used by the pipeline)
│ ├── cameras.core.json # Positions/color/live flag — blocks first paint
│ ├── cameras.labels.json # Names — loads in behind core
│ └── cameras.detail/ # Per-camera detail chunks, fetched on open
├── scripts/
│ ├── scraper.py # CLI entry point — plugin registry, merge modes, maintenance passes
│ ├── store.py # SQLite schema + export to the three-tier payload
│ ├── server.py # Local-only control server behind the in-app "Data Sync" button
│ ├── scrapers/ # One plugin per source, organized by region:
│ │ ├── usa/california/caltrans.py
│ │ ├── usa/road511.py
│ │ ├── canada/bc/drivebc.py
│ │ ├── europe/uk/tfl_london.py
│ │ ├── asia/singapore/lta.py
│ │ ├── oceania/nz/nzta.py
│ │ ├── global/windy.py
│ │ ├── opencctv_bridge.py # Strategic bridge: syncs 200k+ nodes from OpenCCTV
│ │ ├── utils.py # build_feature() — normalizes every source to one schema
│ │ └── ...resolvers (ipcamlive, txdot, host_prober)
│ └── legacy/ # Retired scripts, kept for reference only
└── archive/ # Orphaned data files, kept instead of deleted

Dataset Breakdown

Computed from the live store (python scraper.py --stats), 229,308 cameras total.

By continent

ContinentCamerasShare
North America122,22253.3%
Europe67,09929.3%
Asia32,75514.3%
Oceania4,7722.1%
South America1,2180.5%
Africa1,1670.5%
Antarctica22<0.1%
Unclassified*39<0.1%

By country (every country with 1,000+ cameras — 24 of them, covering 94.5% of the dataset)

CountryCamerasShare
United States110,91248.4%
Japan15,1276.6%
Canada10,8844.7%
United Kingdom7,8293.4%
Italy7,0713.1%
Austria6,5392.9%
Taiwan6,3052.7%
Germany6,0932.7%
Spain5,5302.4%
France5,2092.3%
Switzerland4,8162.1%
Finland3,3981.5%
Australia3,3241.4%
Norway3,0931.3%
Indonesia2,9631.3%
Czechia2,8491.2%
South Korea2,7031.2%
Sweden2,6841.2%
Vietnam2,1070.9%
Poland1,8930.8%
Slovenia1,5480.7%
New Zealand1,3700.6%
Russia1,3650.6%
Hong Kong1,0210.4%
Other (149 countries/territories)12,6755.5%

*A handful of rows (<0.1%) carry a malformed region tag from upstream sources rather than an ISO country code.

Common Commands

GoalCommand
Camera counts by sourcepython scraper.py --stats
Run specific pluginspython scraper.py --plugins drivebc tfl_london nyc_dot
Run everything except Windypython scraper.py --all --exclude windy
Target specific US statespython scraper.py --plugins road511_usa --states CO TN DE
Drop & refresh a source's cameraspython scraper.py --all --replace-source
Rebuild from scratchpython scraper.py --all --fresh
Run plugins concurrentlypython scraper.py --all --parallel

TODO:


Support the Project

If you find this plugin useful, please leave a star on GitHub or consider supporting its development!

ko-fi

License

GitHub License

This project is for educational and open-data visualization purposes only — all camera feeds are sourced from public, non-sensitive government or commercial APIs.

About

Global Surveillance Interface. Visualizing 215k+ global traffic camera streams across 126+ countries.

Topics

Resources

Stars

11 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages