{"id":49754772,"url":"https://github.com/bellingcat/adsb-history","last_synced_at":"2026-05-10T19:00:50.483Z","repository":{"id":339674768,"uuid":"1042672046","full_name":"bellingcat/adsb-history","owner":"bellingcat","description":"Collect and query ADS-B data to find aircraft and trends based on geographic region(s), altitude, bearing, aircraft type and more.","archived":false,"fork":false,"pushed_at":"2026-03-05T04:58:17.000Z","size":13303,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-05T09:58:21.444Z","etag":null,"topics":["ads-b","aircraft","flight-tracking","osint"],"latest_commit_sha":null,"homepage":"","language":"Vue","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bellingcat.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-08-22T11:43:39.000Z","updated_at":"2026-03-05T04:58:21.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/bellingcat/adsb-history","commit_stats":null,"previous_names":["bellingcat/adsb-history"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bellingcat/adsb-history","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bellingcat%2Fadsb-history","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bellingcat%2Fadsb-history/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bellingcat%2Fadsb-history/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bellingcat%2Fadsb-history/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bellingcat","download_url":"https://codeload.github.com/bellingcat/adsb-history/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bellingcat%2Fadsb-history/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32867988,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-10T13:40:02.631Z","status":"ssl_error","status_checked_at":"2026-05-10T13:40:02.145Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ads-b","aircraft","flight-tracking","osint"],"created_at":"2026-05-10T19:00:31.556Z","updated_at":"2026-05-10T19:00:50.474Z","avatar_url":"https://github.com/bellingcat.png","language":"Vue","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg src=\"docs/images/turnstone.png\" style=\"height:188px\" alt=\"Turnstone logo\" /\u003e\n\nTurnstone is a full-stack application for collecting, storing, and querying historical ADS-B aircraft tracking data. This system enables spatial and temporal queries on aircraft positions, with support for filtering by geographic regions, altitude, speed, bearing, aircraft type and more.\n\n![The search interface](docs/images/1.png)\n![A graph of search results over time](docs/images/2.png)\n![Results aggregated by aircraft](docs/images/3.png)\n\nFor more information and background, see [the associated presentation at WHY2025](https://media.ccc.de/v/why2025-242-eye-on-the-sky-building-investigative-journalism-tools-for-analyzing-airplanes).\n\n## Overview\n\nThis project consists of three main components:\n\n1. **Backend Data Loading** - Processes tar1090 heatmap binary files and loads them into PostgreSQL\n2. **Backend API** - Flask-based REST API with Firebase authentication\n3. **Frontend** - Vue.js web application with interactive maps and query builder\n\n## Architecture\n\n### Database Schema\n\nThe main `adsb` table contains:\n- `t` - Timestamp with timezone\n- `hex` - Aircraft ICAO hex identifier\n- `flight` - Flight number/call sign\n- `alt` - Altitude in feet\n- `gs` - Ground speed in knots\n- `geom` - PostGIS geometry (point) for location\n- `bearing` - Heading in degrees\n- `registration` - Aircraft registration number\n- `typecode` - Aircraft type code\n- `category` - Aircraft category (e.g., \"Airliner\", \"General Aviation\", \"UAV\")\n- `military` - Boolean flag for military aircraft\n\nThe `modes` table provides additional aircraft metadata based on ICAO hex codes. This file is identical to the data distributed in the https://github.com/wiedehopf/tar1090-db repo, with the addition of a column for category, and boolean flag for military use, both generated from the aircraft type information with a large language model. This is distributed in `backend-data-loading/modes.csv`. See below for more information about generating this file.\n\n## Prerequisites\n\n### Backend Data Loading\n- Python 3.x\n- PostgreSQL with PostGIS extension\n- Required Python packages (see `backend-data-loading/requirements.txt`)\n\n### Backend API\n- Python 3.x\n- PostgreSQL database (configured)\n- Firebase project with authentication enabled\n- Required Python packages (see `backend-api/requirements.txt`)\n\n### Frontend\n- Node.js (v16+)\n- npm or yarn\n- Firebase project (matching backend)\n\n## Installation\n\n### 1. Backend Data Loading\n\n```bash\ncd backend-data-loading\npip install -r requirements.txt\n```\n\n**Database Setup:**\n\n```sql\n-- Create database\nCREATE DATABASE adsb;\n\n-- Enable PostGIS\nCREATE EXTENSION postgis;\n\n-- Create main table\nCREATE TABLE adsb (\n    t TIMESTAMP WITH TIME ZONE,\n    hex TEXT,\n    flight TEXT,\n    alt BIGINT,\n    gs DOUBLE PRECISION,\n    geom GEOMETRY(Point, 4326),\n    bearing DOUBLE PRECISION,\n    registration TEXT,\n    typecode TEXT,\n    category TEXT,\n    military BOOLEAN\n);\n\n-- Create temporary loading table\nCREATE TABLE adsb_temp (\n    t DOUBLE PRECISION,\n    hex TEXT,\n    flight TEXT,\n    squawk TEXT,\n    lat DOUBLE PRECISION,\n    lon DOUBLE PRECISION,\n    alt BIGINT,\n    gs DOUBLE PRECISION,\n    type INTEGER\n);\n\n-- Create modes table for aircraft metadata\nCREATE TABLE modes (\n    hex TEXT PRIMARY KEY,\n    registration TEXT,\n    typecode TEXT,\n    category TEXT,\n    military BOOLEAN,\n    owner TEXT,\n    aircraft TEXT\n);\n\nCOPY modes FROM 'modes.csv' DELIMITER ',' CSV HEADER;\n\n-- Create indexes\nCREATE INDEX adsb_t_idx ON adsb (t);\nCREATE INDEX adsb_hex_idx ON adsb (hex);\nCREATE INDEX adsb_geom_idx ON adsb USING GIST (geom);\nCREATE INDEX adsb_category_idx ON adsb (category);\n```\n\n### 2. Backend API\n\n```bash\ncd backend-api\npip install -r requirements.txt\n```\n\n**Environment Variables:**\n\nCreate a `.env` file in `backend-api/`:\n\n```env\n# Database Configuration\nDB_HOST=localhost\nDB_NAME=adsb\nDB_USER=your_db_user\nDB_PASS=your_db_password\nDB_PORT=5432\n\n# Firebase Configuration\nFIREBASE_PROJECT_ID=your-firebase-project-id\n\n# Logging\nLOG_FILE=adsb_api.log\n```\n\n**Firebase Setup:**\n\n1. Create a Firebase project at https://console.firebase.google.com\n2. Enable Authentication (Email/Password, Google, etc.)\n3. Download service account credentials JSON\n4. Place credentials in `backend-api/` directory (referenced in `firebase_utils.py`)\n\n### 3. Frontend\n\n```bash\ncd frontend\nnpm install\n```\n\n**Firebase Configuration:**\n\nUpdate `frontend/src/firebase.js` with your Firebase project credentials:\n\n```javascript\nconst firebaseConfig = {\n  apiKey: \"your-api-key\",\n  authDomain: \"your-project.firebaseapp.com\",\n  projectId: \"your-project-id\",\n  storageBucket: \"your-project.appspot.com\",\n  messagingSenderId: \"your-sender-id\",\n  appId: \"your-app-id\"\n};\n```\n\n## Usage\n\n### Data Loading\n\nProcess tar1090 binary files and load into the database:\n\n```bash\ncd backend-data-loading\npython process_adsb_data.py /path/to/data/directory\n\n# Options:\n# --connection-string: Custom database connection string\n# --cleanup-files: Delete files after successful processing\n# --skip-finalize: Skip finalization (for batch processing)\n# --verbose: Enable verbose logging\n```\n\nData can be downloaded from [adsb.lol's data releases](https://github.com/adsblol/globe_history_2025/releases).\n\nFor example, data for October 28th, 2025, once downloaded from Github and extracted, can be imported into the database as follows:\n\n```bash\npython process_adsb_data.py v2025.10.28-planes-readsb-prod-0/heatmap\n```\n\n### Running the API\n\n```bash\ncd backend-api\npython flask-adsb-api.py\n```\n\nThe API will start on `http://localhost:5000` by default.\n\n### Running the Frontend\n\n**Development:**\n```bash\ncd frontend\nnpm run dev\n```\n\n**Production Build:**\n```bash\ncd frontend\nnpm run build\n```\n\nBuilt files will be in `frontend/dist/`.\n\n## API Endpoints\n\n### Authentication\n\nAll endpoints require Firebase authentication. Include the Firebase ID token in the Authorization header:\n\n```\nAuthorization: Bearer \u003cfirebase-id-token\u003e\n```\n\n### GET `/api/adsb/bbox`\n\nQuery aircraft positions within a bounding box with optional filters.\n\n**Query Parameters:**\n- `bbox` - Bounding box: `min_lon,min_lat,max_lon,max_lat`\n- `hex` - Aircraft ICAO hex code\n- `flight` - Flight number/call sign\n- `start_time` - ISO 8601 timestamp (e.g., `2024-01-01T00:00:00Z`)\n- `end_time` - ISO 8601 timestamp\n- `min_alt`, `max_alt` - Altitude range in feet\n- `min_bearing`, `max_bearing` - Bearing range in degrees (0-360)\n- `min_speed`, `max_speed` - Ground speed range in knots\n- `military` - Filter military aircraft (`true`/`false`)\n- `category` - Aircraft category\n- `typecode` - Aircraft type code\n- `limit` - Max records (default: 1000, max: 1000000)\n- `offset` - Pagination offset (default: 0)\n\n**Response:**\n```json\n{\n  \"count\": 100,\n  \"results\": [\n    {\n      \"t\": \"2024-01-01T12:00:00Z\",\n      \"hex\": \"a12345\",\n      \"flight\": \"UAL123\",\n      \"lat\": 37.7749,\n      \"lon\": -122.4194,\n      \"alt\": 35000,\n      \"gs\": 450.5,\n      \"bearing\": 270.5,\n      \"registration\": \"N12345\",\n      \"typecode\": \"B738\",\n      \"category\": \"Airliner\",\n      \"military\": false,\n      \"owner\": \"United Airlines\",\n      \"aircraft\": \"Boeing 737-800\"\n    }\n  ]\n}\n```\n\n### GET `/api/adsb/intersect_bboxes`\n\nFind aircraft that were present in two different bounding boxes within a time period.\n\n**Query Parameters:**\n- `bbox1`, `bbox2` (required) - Two bounding boxes\n- `min_time_diff`, `max_time_diff` - Time difference constraints in seconds\n- All other parameters from `/api/adsb/bbox`\n\n**Response:** Same format as `/api/adsb/bbox` but returns positions from both bounding boxes.\n\n## Frontend Features\n\n### Query Builder\n- Interactive map for drawing bounding boxes\n- Comprehensive filter controls\n- Date/time range selection\n- Aircraft type filters\n- Altitude, speed, and bearing constraints\n\n### Results Visualization\n- Interactive map showing aircraft positions\n- Data table with sorting and pagination\n- Aggregate statistics by aircraft\n- Charts showing temporal distribution\n- CSV export functionality\n\n### Query History\n- Automatic saving of queries to browser IndexedDB\n- Quick replay of previous queries\n- Query naming and organization\n\n## Augmenting tar1090-db\n\nThe tar1090 project distributes an [aircraft database](https://github.com/wiedehopf/tar1090-db) that has information about each aircraft, including its type designation. For example, the database says that the aircraft with hex code `004014` is a Boeing 777-200 (code B772).\n\nThis is augmented by adding ownership information queried from [hexdb.io](https://hexdb.io/). In order to allow searching by natural aircraft type categories (e.g. \"business jet\" vs. \"airliner\"), this dataset was further augmented using a large language model (Anthropic Claude 4.0 Sonnet) which takes the aircraft type and typecode as an input (e.g. \"B772 BOEING 777-200\"), and returns a category (\"airliner\") and a military true/false value (false). The large language model is only used to produce the category and military values. All other search query values in Turnstone are directly from ADS-B data or tar1090-db.\n\nThe augmented file is distributed in `/backend-data-loading/modes.csv`. For more information about this data augmentation process, including the full large language model prompt, see the Jupyter notebook in `/backend-data-loading/augment-aircraft.ipynb`.\n\n*Logo modified from CC licensed photo by [Alberto_VO5](https://www.flickr.com/photos/albertovo5/4646590020).*\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbellingcat%2Fadsb-history","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbellingcat%2Fadsb-history","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbellingcat%2Fadsb-history/lists"}