Emergency Hotline: Call 1-844-363-1423 (United We Dream Hotline)
ICE Encounter

Historical Flight Pattern Analysis

Historical analysis transforms raw flight data into actionable intelligence about deportation operations. This guide covers FOIA strategies, pattern detection, and geospatial visualization.


FOIA Data Acquisition

The ARTS Database

The Alien Repatriation Tracking System (ARTS) is ICE's internal database for deportation logistics. Access requires FOIA litigation.

Attribute Description
Custodian ICE Enforcement and Removal Operations (ERO)
Content Flight manifests, passenger counts, destinations
Access FOIA (often requires litigation)
Key success UWCHR obtained massive ARTS extracts

Effective FOIA Requests

Target Document Agency Request Language
Flight manifests ICE ERO "All flight manifests for removal operations..."
Contractor invoices ICE "Invoices from aviation contractors..."
End of Mission reports ICE Air "All EOM reports for charter operations..."
Flight logs ICE Air "Pilot logs for aircraft N-XXXXX..."

Sample FOIA Request

Pursuant to the Freedom of Information Act, 5 U.S.C. § 552,
I request copies of the following records:

1. All flight manifests for ICE Air Operations removal and
   transfer flights from [start date] to [end date]

2. All "End of Mission" reports for charter aircraft used
   in ICE removal operations during the same period

3. All records identifying aircraft tail numbers (N-numbers)
   and contractors used for removal flights

4. All invoices from CSI Aviation, GlobalX Airlines, and
   Air Wisconsin related to ICE Air Operations

I request a fee waiver pursuant to 5 U.S.C. § 552(a)(4)(A)(iii)
as disclosure serves the public interest in government transparency.

Handling Delays and Denials

Agency Response Counter-Strategy
No responsive records Reframe request, cite known operations
Exemption (b)(7)(E) Appeal; routine logistics are not techniques
Fee estimate Narrow scope, request fee waiver
Indefinite delay File lawsuit (often the only path to ARTS)

Historical Data Sources

Public Repositories

Source Description Access
UWCHR ARTS data FOIA-obtained manifests Published datasets
ADS-B Exchange historical Past 14 days of flights API access
OpenSky Network Academic research access Research agreement
Witness at the Border Analyzed flight records Publications

Bulk Historical ADS-B Data

Provider Retention Access
ADS-B Exchange 14 days via API Subscription
OpenSky Network Years of archived data Research access
Local receiver logs As configured Self-hosted

Archiving Your Own Data

import requests
import json
from datetime import datetime
import sqlite3

def archive_flight_data():
    """Archive current aircraft positions to SQLite"""
    conn = sqlite3.connect('flight_archive.db')
    cursor = conn.cursor()

    cursor.execute('''
        CREATE TABLE IF NOT EXISTS positions (
            timestamp DATETIME,
            hex TEXT,
            flight TEXT,
            lat REAL,
            lon REAL,
            altitude INTEGER,
            ground_speed REAL,
            track REAL
        )
    ''')

    response = requests.get("http://localhost/tar1090/data/aircraft.json")
    data = response.json()

    timestamp = datetime.utcnow()
    for ac in data.get("aircraft", []):
        cursor.execute('''
            INSERT INTO positions VALUES (?, ?, ?, ?, ?, ?, ?, ?)
        ''', (
            timestamp,
            ac.get("hex"),
            ac.get("flight"),
            ac.get("lat"),
            ac.get("lon"),
            ac.get("alt_baro"),
            ac.get("gs"),
            ac.get("track")
        ))

    conn.commit()
    conn.close()

Flight Categorization

Operational Categories

Category Definition Identification
Removal Direct international deportation Origin: US hub → Destination: Foreign
Removal Return Empty repositioning flight Destination: US hub, fast/high profile
Removal Connection Domestic leg before removal Same aircraft, same day as removal
Shuffle Domestic inter-facility transfer Both endpoints domestic

Category Identification Algorithm

def categorize_flight(origin, destination, same_day_flights):
    """Categorize a flight segment"""

    US_STAGING_HUBS = ["AEX", "BRO", "SAT", "IWA", "MIA"]
    FOREIGN_AIRPORTS = ["PAP", "SJO", "GUA", "MEX", "SAL"]

    origin_is_us = origin in US_STAGING_HUBS
    dest_is_foreign = destination in FOREIGN_AIRPORTS
    dest_is_us = destination in US_STAGING_HUBS

    if origin_is_us and dest_is_foreign:
        return "REMOVAL"
    elif dest_is_us and not origin_is_us:
        # Check if this is a return leg
        for flight in same_day_flights:
            if flight["category"] == "REMOVAL":
                return "REMOVAL_RETURN"
        return "SHUFFLE"
    elif origin_is_us and dest_is_us:
        # Check if there's a removal later that day
        for flight in same_day_flights:
            if flight["origin"] == destination and flight["category"] == "REMOVAL":
                return "REMOVAL_CONNECTION"
        return "SHUFFLE"

    return "UNKNOWN"

Pattern Analysis Methods

Temporal Patterns

Pattern Indicator Analysis Method
Daily rhythm Peak departure times Time-series histograms
Weekly patterns Day-of-week variations Weekly aggregation
Surge detection Sudden volume increases Standard deviation analysis
Seasonal trends Long-term variations Moving averages

Surge Detection Algorithm

import numpy as np
from collections import defaultdict

def detect_surge(flight_data, baseline_days=30, threshold_std=2):
    """Detect enforcement surges by comparing to baseline"""

    # Group flights by date
    daily_counts = defaultdict(int)
    for flight in flight_data:
        date = flight["timestamp"].date()
        daily_counts[date] += 1

    # Calculate baseline statistics
    counts = list(daily_counts.values())
    baseline_mean = np.mean(counts[-baseline_days:-1])
    baseline_std = np.std(counts[-baseline_days:-1])

    # Check most recent day
    latest_count = counts[-1]
    z_score = (latest_count - baseline_mean) / baseline_std

    if z_score > threshold_std:
        return {
            "surge_detected": True,
            "current_count": latest_count,
            "baseline_mean": baseline_mean,
            "deviation": z_score
        }

    return {"surge_detected": False}

Route Pattern Analysis

Pattern Description Detection
Direct routes Nonstop to destination Single origin-destination pair
Layover routes Intermediate stops Multiple legs, same aircraft
Third-country transfers Indirect deportation Non-standard destination sequencing
Hub concentration Staging pattern Geographic clustering

Geospatial Analysis

Tools and Libraries

Tool Use Case Access
QGIS Desktop GIS analysis Open source
PostGIS Spatial database Open source
Geopandas Python geospatial Python library
Folium Interactive web maps Python library
Kepler.gl Large-scale visualization Web platform

Creating Flight Path Maps

import folium
import pandas as pd

def create_flight_map(flight_positions):
    """Generate interactive map of flight paths"""

    # Create base map centered on US
    m = folium.Map(location=[39.8283, -98.5795], zoom_start=4)

    # Group positions by flight
    for hex_code in flight_positions["hex"].unique():
        flight_data = flight_positions[flight_positions["hex"] == hex_code]

        # Create path from positions
        coordinates = list(zip(
            flight_data["lat"],
            flight_data["lon"]
        ))

        # Add flight path
        folium.PolyLine(
            coordinates,
            weight=2,
            color='red',
            opacity=0.8,
            popup=f"Flight: {hex_code}"
        ).add_to(m)

    return m

Heatmap Generation

from folium.plugins import HeatMap

def create_activity_heatmap(positions):
    """Generate heatmap of flight activity"""

    m = folium.Map(location=[39.8283, -98.5795], zoom_start=4)

    # Extract coordinates
    heat_data = [[row["lat"], row["lon"]] for _, row in positions.iterrows()]

    # Add heatmap layer
    HeatMap(heat_data).add_to(m)

    return m

Staging Hub Analysis

Analysis Method
Hub identification Cluster analysis of departure points
Throughput Count departures per airport per period
Routing patterns Origin-destination matrices
Capacity utilization Compare to known fleet size

Correlation Analysis

Linking Flights to Events

Data Source Correlation Target
News reports Raid announcements, policy changes
Court filings Emergency stay denials
Rapid response logs Community reports of arrests
Government announcements Operation declarations

Example: Operation Surge Detection

def correlate_with_events(flight_data, events):
    """Correlate flight surges with known events"""

    correlations = []

    for event in events:
        event_date = event["date"]

        # Count flights 3 days before/after event
        window_flights = [
            f for f in flight_data
            if abs((f["timestamp"].date() - event_date).days) <= 3
        ]

        # Check for elevated activity
        if len(window_flights) > baseline_threshold:
            correlations.append({
                "event": event["description"],
                "date": event_date,
                "flight_count": len(window_flights),
                "aircraft": list(set(f["hex"] for f in window_flights))
            })

    return correlations

Visualization for Advocacy

Effective Presentations

Visualization Type Best For
Route maps Showing deportation destinations
Time series Demonstrating surge patterns
Heatmaps Geographic concentration
Infographics Public education
Interactive dashboards Ongoing monitoring

Key Metrics to Display

Metric Description
Total flights Volume over time period
Destinations Countries receiving deportees
Surge magnitude Percentage increase vs. baseline
Hub activity Departures per staging airport
Route changes New or discontinued destinations

Report Structure

Section Content
Executive summary Key findings in 2-3 sentences
Methodology Data sources and analysis methods
Volume analysis Flight counts and trends
Route analysis Destinations and patterns
Correlation Links to policy/enforcement events
Recommendations Advocacy implications

Data Management

Database Schema

CREATE TABLE flights (
    id SERIAL PRIMARY KEY,
    hex VARCHAR(6) NOT NULL,
    callsign VARCHAR(8),
    origin VARCHAR(4),
    destination VARCHAR(4),
    departure_time TIMESTAMP,
    arrival_time TIMESTAMP,
    category VARCHAR(20),
    verified BOOLEAN DEFAULT FALSE
);

CREATE TABLE positions (
    id SERIAL PRIMARY KEY,
    flight_id INTEGER REFERENCES flights(id),
    timestamp TIMESTAMP,
    lat DECIMAL(9,6),
    lon DECIMAL(9,6),
    altitude INTEGER,
    ground_speed DECIMAL(6,1)
);

CREATE TABLE aircraft (
    hex VARCHAR(6) PRIMARY KEY,
    n_number VARCHAR(10),
    operator VARCHAR(100),
    aircraft_type VARCHAR(50),
    confidence VARCHAR(10),
    last_verified DATE
);

CREATE INDEX idx_positions_flight ON positions(flight_id);
CREATE INDEX idx_positions_timestamp ON positions(timestamp);
CREATE INDEX idx_flights_hex ON flights(hex);

Data Retention

Data Type Retention Storage
Position data 30 days rolling Compressed archive
Flight summaries Indefinite Primary database
Verified flights Indefinite Primary database
FOIA documents Indefinite Document store

Related Resources


Last updated: March 25, 2026

Legal Disclaimer

This website does not provide legal advice. The information provided on this site is for general informational and educational purposes only. It does not create an attorney-client relationship.

Information on this website may not be current or accurate. Immigration law is complex and varies by jurisdiction and individual circumstances. Always consult with a qualified immigration attorney for advice specific to your situation.

Neither ICE Encounter, its developers, partners, nor any contributors shall be liable for any actions taken or not taken based on information from this site. Use of this site is subject to our Terms of Use and Privacy Policy.