FAA Airmen Certificate Change Monitor
Pricing
$10.00 / 1,000 airman record changeds
FAA Airmen Certificate Change Monitor
Private change monitor for named FAA airmen by UNIQUE ID. Bills only on real change in the monthly FAA Releasable Airmen file: certificate level upgrade, rating change, medical class or date change, plus a distinct event when a record is absent from two different FAA releases. No names or addresses.
Pricing
$10.00 / 1,000 airman record changeds
Rating
0.0
(0)
Developer
Radu Furtuna
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
5 days ago
Last modified
Categories
Share
Watches specific airmen in the official FAA Civil Aviation Registry Airman Directory Releasable File
(registry.faa.gov/database/CS<MM><YYYY>.zip) and delivers — and bills — only on a genuine change since
your last check. Never a re-delivery of an unchanged record.
Positioning, stated plainly. Delta monitoring of this file is not unique — at least one other Apify actor already reads the same monthly FAA archive, already accepts a list of FAA unique IDs, already keeps a durable "emit only what is new or changed since the last run" store, and already bills only for delivered results. This actor is not sold as "the only delta monitor". It is built around two things that a "new-or-changed" feed structurally cannot give you:
- Absence as a first-class event. A feed that emits records which are new or changed can only tell you about rows it sees. To notice that a specific airman is no longer in the file at all you have to keep a durable index of the IDs you are watching and diff the snapshot against it. That is what this actor does, and the event it raises is narrow and literal: "this record was absent from two consecutive, genuinely different FAA releases." Read the next section for exactly what that does and does not mean.
- A privacy-narrowed output for credentialing and compliance — no names, no street addresses, no ZIP codes, ever (see Privacy below). That is a deliberate narrowing of the product, not a feature the lead-generation scrapers are missing.
If what you need is a bulk export with names and addresses for lead generation, the other FAA actors on Apify Store are the right tool and are cheaper for that job.
Not a certification of flight privileges and not legal advice. This is an informational monitor of a public government file's publication state. It is not proof that anyone currently holds valid flight privileges, not a verification of a medical certificate on any given date, and not a substitute for a direct request to the FAA Airmen Certification Branch before any decision that matters (hiring, crew assignment, insurance underwriting, Part 135/145 compliance).
What it watches
One watch = one FAA UNIQUE ID (the letter A or C followed by exactly 7 digits, e.g. A0000014) —
the stable identifier FAA itself uses as the key across all four files in the archive. Per run the actor
checks each watch against the current monthly snapshot and reports:
new— the first time this airman was found (the very first sighting of a watch is a free, unbilled baseline;newfires only for a later first appearance).record_changed— something in the tracked professional record changed: a certificate level upgrade (Student → Private → Commercial → ATP), a certificate type gained or lost, ratings or aircraft type ratings added or removed, or the medical class / medical date / medical expiry / BasicMed dates changed. The row'schangedFieldssays which.removed_from_releasable_file— the record, previously found, is now absent from the releasable file entirely, on two consecutive, genuinely different monthly releases (see "Two-strike" below). This is a statement about the FAA publication only — never a report that a certificate was revoked, suspended or lost. See "What the absence event does and does not mean".restored— an airman previously confirmed removed is found again.candidate_removed— first absence on a single release. Informational only: delivered withbilled: false, never charged. If the airman reappears before a second, different release confirms the absence, the candidate is silently cancelled and nothing is billed either way.
Every genuine transition (new, record_changed, restored, and a confirmed
removed_from_releasable_file) is billed once under a single event. The same unchanged record is never
billed twice, and candidate_removed is never billed.
Privacy: no names, no home addresses — on purpose
This is a register of private individuals. The FAA file itself contains each airman's full name and home mailing address, and Public Law 106-181 does require FAA to release them. This actor still does not read those fields into its model and does not emit them anywhere — not in the dataset, not in the webhook, not in the digest.
What you get: the airmanId you supplied, the full certificate structure (type, level, ratings, aircraft
type ratings, expiry), medical class and dates, and coarse geography — city, state, country and FAA
region, with no street address and no ZIP code.
Address fields are also deliberately excluded from the change hash: a pilot moving house is not a change in professional standing, so a relocation never produces a row and never costs you anything. If you need a name-and-address list for lead generation, this is the wrong actor — that is what the bulk FAA scrapers on Apify Store are for. This one is built for credentialing and compliance, where the address is not just unnecessary but a liability.
Monthly cadence — read this before scheduling
FAA republishes this file once a month, on the 1st. That is the ceiling on freshness of the source
itself, not a limitation of this implementation. In the normal case, running the actor more often than
monthly surfaces nothing new — the exception is a mid-month reissue of the same month's archive, which
this actor does detect whenever the reissued file differs in size, Last-Modified or ETag from the
one already processed (see the known limitation below for the case where it does not). Either way, this
actor is built so that you do not pay for trying:
- Before downloading anything, the actor makes one cheap ranged request (200 bytes) and compares the
response headers (month, exact size,
Last-Modified,ETag) with those of the last release it fully processed. If they match and every watch already has a baseline, the run ends immediately asno_new_release: no 57 MB download, no history write, zero charges. (HEADcannot be used here —registry.faa.govanswersHEADwith HTTP 503; a rangedGETanswers206 Partial Content.) Those headers are only ever a reason to download or not download; nothing is decided by them. Once the archive is in hand, its SHA-256 is what identifies the release. Known limitation: this cheap check is a heuristic, not a guarantee. If FAA reissues a corrected archive for the same month and the new file happens to keep the same size,Last-ModifiedandETagas the one already processed, this actor will not notice — the probe matches, the download is skipped, and the correction is only picked up once the following month's release changes at least one of those headers (or, at the latest, once the following month's file is published under a new name/size entirely). We deliberately do not trade this away for a full monthly re-download-and-hash on every run: the archive is 57 MB, and "just download it every time to be sure" turns a near-free monthly check into a 57 MB transfer on every single run, most of which would find nothing new. If your use case cannot tolerate a same-headers reissue going unnoticed for up to a month, do not rely on this actor's freshness check for that — that risk window is a property of the FAA source's own publishing habits, not something this actor can close without materially changing its cost profile. - If you add a new watch mid-month, that run does download the archive so the new watch gets its baseline immediately rather than waiting for the next release.
- A release is only marked as processed once every watch in the run has finished successfully. If a
run is cut short — the run's wall-clock deadline, a lost monitor lease, your own spend cap, or one watch
whose snapshot could not be trusted — that release is not recorded as done, and the next run
downloads and re-processes it instead of skipping it. Rows already delivered are not re-delivered or
re-charged: the right to write a row and bill for it is granted by an atomic gate (a single
RequestQueue.addRequestper item, in a dedicated durable journal that is never cleared) before the first irreversible step, keyed on the airman, the change sequence and the content hash — the per-watch index is only advanced after a row reaches a terminal state. This is at-most-once delivery, not exactly-once: a crash right after the right to deliver is granted can lose that one event permanently (it is recorded internally as unresolved and never retried), but you are never billed twice for the same event. That guarantee holds as long as the claim journal itself is not deleted or recreated (an account-level action outside the actor's control), and it applies from the build that introduced this atomic gate onward. Every run reports this incoverageasreleaseAccepted(plusreleaseNotAcceptedReason) andclaimJournalSize(a best-effort, eventually-consistent size of that journal, for operational monitoring only). - A download that fails on a transient network error (timeout, 5xx, interrupted stream) is retried exactly once inside the run's fixed byte budget. Nothing else in the actor retries.
Recommended schedule: once a month, on the 2nd–3rd (a small delay past the 1st absorbs publication lag). Anything more frequent is harmless and near-free; its only payoff is catching a mid-month reissue sooner, as described above. If the current month's file is not up yet, the actor automatically falls back to the previous month's file rather than failing.
Two-strike removal confirmation, tied to the release
A single snapshot passing the integrity gate (below) only proves the file is not catastrophically truncated; a file that is genuinely valid but a few percent short still passes. To avoid billing a disappearance that is really a data artefact, this actor requires the absence to repeat:
- First absence of a previously-found airman → recorded internally as a pending candidate and
delivered as
candidate_removed,billed: false. The last known record is left untouched. This row is free, but a Dataset write is still irreversible, so it goes through its own at-most-once gate (keyed without the run id, on a durable "disappearance cycle" counter) — a crash right after delivery can lose this one informational row, but it is never delivered twice for the same cycle. - Reappears before confirmation → the candidate flag is cleared. Nothing billed, nothing reported as removed or restored.
- Still absent on a different monthly release → now confirmed and billed as
removed_from_releasable_file.
The words "different release" are load-bearing. The source only changes monthly, so "two consecutive
runs" would be meaningless — you could run the actor three times in one afternoon against the identical
file. Confirmation is keyed to release identity, which is the SHA-256 of the archive the run actually
downloaded — not to a header. Repeated runs against the same monthly file therefore never advance the
two-strike counter, and neither does a re-download of byte-identical content served with a different
Last-Modified or ETag. Conversely, if FAA reissues a corrected file for the same month and the run
actually downloads it (see the known limitation above — a same-headers reissue can go undownloaded until
the next month), the hash differs and it correctly counts as a new release even if its size is unchanged.
Practical consequence: a confirmed absence reaches you one month after the first one (longer still if
a same-headers reissue delays detection further, per the limitation above). That is the honest cost of
not billing you for a false alarm.
What the absence event does and does not mean
The event is about the FAA file, not about anybody's licence. removed_from_releasable_file states
exactly one fact and nothing more:
This
UNIQUE IDwas present in the FAA Airman Directory Releasable File, and is now absent from it in two consecutive, genuinely different releases of that file.
It is not a report that a certificate was revoked, suspended, cancelled, surrendered or lost, and it must never be read, forwarded or resold as one. This actor cannot know any of that, because the file does not say it.
Why it cannot: FAA's own documentation, shipped inside the archive as HelpComm.pdf ("Airman Directory
Releasable File, Comma Delimited", Airmen Certification Branch AFS-760), states two things at once:
"Only active Certificates are processed; At least 1 Certificate must be active for Airman to be in file."
"This file contains the names, addresses, and certificate information of those airmen who did not respond to indicate that they wished to withhold their address information."
So a record leaves the file when either the airman no longer has an active certificate in it or the airman exercised their statutory right (Public Law 106-181 §715) to withhold address release — a purely administrative act with no bearing on their credentials at all. The file carries no field that distinguishes these two, and neither does this actor. The honest use of the event is as a prompt to check: something about this airman's presence in the public FAA publication changed, so ask the FAA Airmen Certification Branch directly before any decision that matters.
There is also a third possibility the actor guards against rather than reports: a partial or inconsistent
snapshot. If a watched ID turns up in the certificate files but is missing from both basic files, the
snapshot is not trustworthy for that airman, so the run reports source_access_limited for that watch —
no candidate row, no charge, no advance of the two-strike counter — and the same FAA release is downloaded
and re-processed on the next run rather than being marked as done.
Honest limits
-
The durable dataset is a delivery-attempt log, not a guaranteed mirror of the default dataset. Each row is written to the named durable dataset first, then mirrored to the run's default dataset, and only then does billing proceed for that row. If the durable write succeeds but the default-dataset mirror fails (a transient Apify storage error, say), the item is marked
dataset_unknown, billing for it is permanently blocked (fail-closed — we never charge for a row we cannot confirm was delivered), and that exact row is not recreated. The durable dataset can therefore hold a small number of orphan rows that were never mirrored and never billed. The default dataset is the canonical log of rows successfully written to this run's output (see itsrun_summaryrow) — but a default-dataset row does not by itself prove payment: the row is written beforeActor.charge()runs, so if charging then fails or returnscharge_unknown, the row exists but is not confirmably paid.run_summary.eventsBilledand Apify's own billing ledger are the source of truth for confirmed payment, not the presence of a row in either dataset. -
Nothing is classified until the whole snapshot passes a fail-closed integrity gate. Before a single watch is judged new/changed/removed, every run validates the entire download: the ZIP passes
testzip()(no CRC corruption); it contains exactly the six expected members (PILOT_BASIC.csv,PILOT_CERT.csv,NONPILOT_BASIC.csv,NONPILOT_CERT.csv,HelpComm.pdf,index_c.txt) — not one more, not one fewer; each member's decompressed size and their total are under sane caps; every CSV decodes as strict UTF-8 with no silent replacement of invalid bytes; every header matches its expected column list exactly (a vanished or renamed column is caught here, distinctly from an empty value in one row);UNIQUE IDmatches FAA's documented^[AC][0-9]{7}$and is unique across the whole file in each Basic file, with(UNIQUE ID, TYPE)unique across each Certificate file; required fields are non-empty; the medical field group is all-present-or-all-absent; ratings have no gaps; and each file's row count is above an absolute floor and not a material drop (more than 5%) from the last snapshot that itself passed this gate. Any failure ends the run assource_access_limitedfor every watch: no baseline is read or written, no removal or change event fires, and nobody is charged. This exists specifically so a syntactically valid but truncated archive (a cut-off download, a proxy returning a partial 200) cannot turn every tracked airman into a billable disappearance. -
What was verified live and what was not. On 2026-09-13 the September archive was downloaded and fully parsed: 592,700 pilot Basic rows, 682,411 pilot Certificate rows, 380,007 and 393,413 non-pilot rows; zero duplicate
UNIQUE IDs; all four files strictly sorted byUNIQUE ID; Basic and Certificate ID sets identical within each family; 63,214 airmen present in both families with byte-identical Basic rows; every field's nullability counted individually; and the format claims above cross-checked against FAA's ownHelpComm.pdffrom inside the archive. The change signal itself was verified by the earlier diff of the August and September archives (3,617 new IDs, 2,769 gone, 708LEVELchanges, 1,428 rating changes, 16,295 medical-date changes). What was not observed is a single named airman actually leaving the file between two runs of this actor — the source updates monthly and the build window was hours. The "disappearance = no active certificate or address opt-out" conclusion rests on FAA's own documented file contract, not on a watched live transition. -
Non-US airmen have no
state. FAA leavesSTATEblank for foreign addresses (16,979 of 592,700 pilot rows live).countryandcityare always present. -
Medical fields only exist for pilots.
MED CLASS/MED DATE/MED EXP DATEare populated only where the airman holds an active Certificate Type "P" (256,374 of 592,700 pilot rows live). An A&P mechanic legitimately has none, and that absence is not a change. -
This actor does not search by name. You supply the
UNIQUE ID. If you only have a name, look the airman up first — this actor deliberately provides no name-based discovery over a register of private individuals.
Coverage and billing record
Every run writes a coverage record with per-watch status/reason/matched, the FAA release identity
actually used (releaseId, releaseKey — month plus the SHA-256 of the downloaded archive —
noNewRelease, releaseAccepted, releaseNotAcceptedReason), per-file snapshot row counts,
removedFromReleasableFileCount (confirmed, billed second-strike removals only),
pendingRemovalCandidateCount (unbilled first-strike candidates), and recordsDelivered /
recordsBilled — enough to reconcile every charge against every row. A watch that never matched (a typo,
or an ID FAA has never issued) is reported as matched: false, status: "ok" — not an error.
What it does not do
- Does not emit names, street addresses or ZIP codes — ever (see Privacy above).
- Does not scrape any FAA web page; it uses FAA's own official monthly bulk export.
- Does not re-deliver a record that has not changed.
- Does not report an address change (deliberately excluded from the change hash).
- Does not cover certificate actions, enforcement or accident history — the releasable file contains none of that.
- Does not report revocations, suspensions or surrenders, and does not infer them from an absence.
- Does not claim to be the only change monitor for this file. See "Positioning, stated plainly" at the top.