Skip to main content
The Webcam layer provides global visual intelligence by overlaying webcam locations on the map, with interactive tooltips showing preview images and a pinned webcam panel for persistent monitoring of key locations.

Data Source: Windy Webcams API v3

The primary data source is the Windy Webcams API, which provides approximately 65,000 camera locations worldwide.

What the API provides

Seed-time fields (bulk fetch with include=location,categories): On-demand fields (per-camera fetch with include=images,urls):

Free tier limitations

  • Image token URLs expire after 10 minutes
  • Bounding-box queries capped at 10,000 results per request (seeder uses adaptive quadrant splitting to work around this)
  • Rate limits apply (seeder uses sequential regional fetches)

API key configuration

The webcam layer requires a WINDY_API_KEY environment variable. Get a free key at api.windy.com. Without the key:
  • Seeder exits gracefully with “WINDY_API_KEY not set, skipping webcam seed”
  • Image handler returns { error: 'unavailable' } and tooltips show “Preview unavailable”
  • Map layer still renders markers from cached geo data (if previously seeded), but image previews are unavailable

Architecture

Backed by endpoints

The webcam layer does not hydrate marker or preview data from the bootstrap payload. Viewport reads are direct WebcamService RPC calls against the seeded Redis geo index, and preview/player URLs are fetched only after a user interacts with a marker.

Server-side clustering

The listWebcams handler performs server-side spatial clustering based on zoom level. At low zoom, nearby cameras are grouped into cluster markers showing a count. At higher zoom, individual markers appear. This keeps the map performant even when thousands of cameras are in view.

Caching

Three cache layers work together to minimize latency and external API calls:

Expected latency behavior

On first interaction after a container start, there is a noticeable delay as caches are cold:
  1. Map viewport changelistWebcams RPC → server performs Redis geo search, builds clustered response, caches it. Subsequent identical viewports return instantly from Redis cache (24h TTL).
  2. First click on a webcam markergetWebcamImage RPC → server calls Windy API (network round-trip to external service), caches the response for 5 minutes server-side. The client also caches for 9 minutes — so re-clicking the same webcam within 9 minutes is instant with no server call.
  3. Pinning a webcam → the player iframe loads from Windy’s CDN (another external round-trip for the embed page). This is not cached by us — the browser handles iframe caching.
Once caches are warm, the only external calls are for webcams not viewed in the last 5-9 minutes.

Redis data is ephemeral

Redis data does not survive container rebuilds. After rebuilding the stack, the seeder (scripts/seed-webcams.mjs) must re-run to repopulate the geo index and metadata. Without seeded data, the webcam layer will show no markers. Viewport response caches and image caches will rebuild organically as users interact with the map.

No automatic re-seeding (known gap)

This is a known limitation that needs to be addressed in a follow-up PR. The seeder writes geo and metadata keys to Redis with a 24-hour TTL, but nothing triggers a re-seed when those keys expire. After 24 hours without a manual re-seed, the webcam layer silently goes blank. Current ways to re-seed:
  • Run scripts/seed-webcams.mjs from the host
  • Run scripts/run-seeders.sh (runs all seeders including webcams)
  • Railway cron (recommended): schedule seed-webcams.mjs as a Railway cron service every 12-18 hours to stay ahead of the 24-hour TTL expiry

Pinned Webcams Panel

Users can pin webcams from map tooltips to a persistent side panel. The panel displays up to 4 webcams simultaneously in a 2x2 grid of embedded Windy player iframes.

Features

  • 2x2 iframe grid: Four active webcam players visible at once
  • Toggle on/off: Webcams can be toggled between active (showing in grid) and inactive (in list only)
  • Overflow list: When more than 4 webcams are pinned, a scrollable list appears below the grid for managing all pins
  • Pin from any renderer: Pin buttons appear in webcam tooltips across all three map renderers (SVG, Globe, DeckGL)
  • Persistence: Pinned webcams survive page reloads via localStorage
  • Custom events: Panel updates reactively when pins change from any source

Storage

Pinned webcam data is stored in localStorage under the key wm-pinned-webcams. Each entry contains:
Maximum 4 webcams can be active (showing in grid) at any time. The total number of pinned webcams is not limited.

Current Limitations

Not live video

This is the most important limitation to understand. The Windy player does not show live video streams. Most webcams in the Windy network capture still images at periodic intervals (every 5-15 minutes). The embedded player compiles these stills into a timelapse, typically showing the last 24-72 hours of captures. This means:
  • The “player” is a timelapse of recent snapshots, not a live feed
  • There is no way to filter for live-streaming cameras via the Windy API
  • Real-time situational awareness is limited to the latest captured image (visible in the tooltip preview)

No live video API exists at free tier

Free sources of actual live video webcam feeds with structured APIs do not currently exist. Live video requires streaming infrastructure (RTSP/HLS/WebRTC) which is expensive to operate. Known live sources are either paid, partner-only, or have no API:

Other limitations

  • Free tier attribution: Windy requires attribution when using free API tier
  • Image token expiry: Preview image URLs from Windy expire after ~10 minutes; re-fetching is needed for stale tooltips
  • Seed coverage: The seeder caps at 10K cameras per regional bounding box; adaptive quadrant splitting mitigates this but very dense regions may still miss cameras
  • No status filtering: Inactive/offline cameras may appear on the map with broken previews
  • iframe sandbox: Player iframes use allow-scripts allow-same-origin allow-popups sandbox policy

Future Phases

Phase 2: US DOT 511 State APIs

Tens of thousands of traffic cameras across 20+ US states. Free with developer key per state. These are also periodic still images (refresh every 30-60 seconds), not live video, but update more frequently than Windy cameras. Target states: NY (511ny.org), CA (511.org), GA (511ga.org), AZ (az511.com), UT. Challenge: Each state has a slightly different schema requiring normalizing adapters.

Phase 3: OpenWebcamDB

Supplementary source with ~2,052 curated cameras. Free tier limited to 50 requests/day. Clean REST API but small dataset. Requires aggressive caching strategy.