Skip to content

fix: follow the FR24 airports and airlines page redesign - #134

Merged
JeanExtreme002 merged 2 commits into
mainfrom
fix/fr24-airports-airlines-redesign
Nov 9, 2026
Merged

JeanExtreme002 merged 2 commits into
mainfrom
fix/fr24-airports-airlines-redesign

Conversation

@JeanExtreme002

@JeanExtreme002 JeanExtreme002 commented Nov 9, 2026 •

Copy link
Copy Markdown
Owner

Why

The scheduled live runs of the three packages (Python, Node, Go) went red on 2026-11-09. FlightRadar24 redesigned its data pages:

  • https://www.flightradar24.com/_json/airports.php, the single-payload airports feed, now returns 404. get_airports() failed in every port.
  • https://www.flightradar24.com/data/airlines is no longer an HTML table. The parsers found no <tbody> and returned an empty list (assert 0 >= 100).
  • data-cloud.flightradar24.com/zones/fcgi/feed.js answered 429 Too Many Requests from the shared GitHub runners. This one is rate limiting, not a code bug.

What changed

Airports. Airports now live on Inertia pages. /data/airports names every country and declares the asset version; /data/airports/<country> lists the airports, or the states for the largest countries (US, Brazil, ...); /data/airports/<country>/<state> lists those. get_airports() reads the index and crawls one page per country and state, max_workers at a time, asking for the page JSON with the Inertia headers (x-inertia, x-inertia-version) and falling back to the HTML, whose data-page attribute carries the same object, on a 409. Results are grouped by country in the order asked, deduplicated, and an unknown country logs a warning.

Airlines. Each airline is a link to its data page, with the name in a titled element, the IATA/ICAO codes as badges and the fleet size only under "Largest fleets". The parser follows the new markup and merges an airline the page lists in several sections.

Tests. The offline fixtures model the new pages and are shared byte for byte by the three ports. Parser tests mirror each other, and a new offline suite per port pins the crawl: request order, version header, 409 fallback, grouping by country, deduplication and the unknown-country warning. The Python live tests also retry on HTTP 429.

Docs. The "Airports list" sections of the three ports describe the per-page crawl and the missing coordinates.

Behaviour changes

  • Airport.latitude, longitude and altitude are None/null/zero-value for airports returned by get_airports(). The listing no longer carries them; get_airport(code) still does.
  • n_aircrafts is None for most airlines. The page only prints the fleet size for the largest ones.
  • Core.airports_json_url (Python), airportsJsonUrl (Node) and endpoints.airportsJSON (Go) were removed, along with the numeric-coercion helpers that only served the old JSON.
  • No version bump in this PR.

Verification

Port Lint / types Offline tests Live
Python flake8, mypy clean 103 passed get_airlines() and get_airports("uruguay") OK
Node eslint, tsd clean 97 passing 2142 airlines; Uruguay airports OK
Go gofmt, vet, staticcheck clean; 93.4% coverage; race clean all pass airlines, BR+US (≥1800 airports), full crawl of every country (13s) OK

The 429 on the feed is environmental and may still flake the scheduled runs.

Follow-up in this PR

The first CI run of this branch surfaced two more things, fixed in the second commit:

  • Node 18/20: the live airports suite crawls one page per country and state and ran past mocha's 10 second default. The suite now gets 60 seconds.
  • Go 1.27 (make security): govulncheck flags github.com/andybalholm/brotli v1.2.2 (GO-2026-6888). Bumped to v1.2.7. Pre-existing, unrelated to the redesign, but it blocks the Go job.

The scheduled live runs of the three packages went red on 2026-11-09:
FlightRadar24 redesigned its data pages.

- `/_json/airports.php`, the one-payload airports feed, is gone (404).
  Airports are now listed on Inertia pages: `/data/airports` names every
  country and declares the asset version, `/data/airports/<country>`
  lists the airports, or the states for the largest countries, and
  `/data/airports/<country>/<state>` lists those. `get_airports()` now
  reads the index and crawls one page per country and state,
  `max_workers` at a time, asking for the page JSON with the Inertia
  headers and falling back to the HTML (whose data-page attribute
  carries the same object) on a 409. The listing no longer carries
  coordinates or altitude: those fields are None, and `get_airport(code)`
  has them.
- `/data/airlines` is no longer a table: airlines are list entries with
  the name in a titled element, the codes as badges and the fleet size
  only under "Largest fleets". The parser follows the new markup and
  merges an airline the page lists in several sections.

The offline fixtures model the new pages (shared by the three ports),
the parser tests mirror each other, and a new offline suite pins the
crawl: request order, version header, 409 fallback, grouping by country,
deduplication and the unknown-country warning. The Python live tests
also retry on HTTP 429, which the shared CI runners trip on the feed.
- nodejs: the live airports suite crawls one page per country and state
  and ran past mocha's 10 second default on Node 18 and 20; it now gets
  60 seconds, like the Go live tests.
- go: govulncheck flags github.com/andybalholm/brotli v1.2.2
  (GO-2026-6888); bumped to v1.2.7, which fixes it.
@JeanExtreme002
JeanExtreme002 merged commit 5f92013 into main Nov 9, 2026
13 checks passed
@github-actions
github-actions Bot deleted the fix/fr24-airports-airlines-redesign branch November 9, 2026 06:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant