# Sites watched from orbit, free

> Every energy site (refinery, terminal, lng, depot) and oil port Geo watches by satellite: its last NASA FIRMS thermal anomaly (heat above the site's own normal at a satellite pass, never a confirmed strike), anomalies in 365 days, its latest clear Sentinel-2 view and, for a port, the latest week's Sentinel-1 vessel count against its own normal. Each site has a page at /geo/site/<id>.

Source: https://firmtape.com/docs/developers/geo/free-sites

Every energy site (refinery, terminal, lng, depot) and oil port Geo watches by satellite: its last NASA FIRMS thermal anomaly (heat above the site's own normal at a satellite pass, never a confirmed strike), anomalies in 365 days, its latest clear Sentinel-2 view and, for a port, the latest week's Sentinel-1 vessel count against its own normal. Each site has a page at /geo/site/<id>.

`GET https://firmtape.com/geo/api/sites`

Plan Free · No key · Limit Free JSON, every watched site · Version 1.0.0

**This endpoint serves:** [GEO: The map and the feed](https://firmtape.com/docs/geo#records-map), [GEO: The API, webhooks and MCP](https://firmtape.com/docs/geo#geo-api). **Plan:** [Free](https://firmtape.com/features/replay). Free, no account

## Response

{ count, sites: [{ id, name, kind, country, region, lat, lon, watched_since, last_anomaly_utc, anomalies_365d, view, occupancy }], attribution }

## Request

```sh
curl \
  "https://firmtape.com/geo/api/sites"
```

```python
import os, requests

H = {}
r = requests.get("https://firmtape.com/geo/api/sites", headers=H)
print(r.status_code, r.text[:500])
```

```js
const r = await fetch("https://firmtape.com/geo/api/sites", {
  method: "GET",
  headers: {  },
});
console.log(r.status, await r.text());
```
