Ephemera

ephemera.space
built 2026-09-03 22:00 UTC

Every eight hours, SpaceX publishes where each of about eleven thousand Starlink satellites will be for the next three days, and how sure it is. Eight hours later that set is gone, replaced by the next one. Ephemera keeps them, and measures what the public catalogue can see.

The files carry a full position and velocity uncertainty every sixty seconds, read from the feed on 30 August 2026. Starlink is the only operator with public covariance; other operators enter via CelesTrak SupGP without covariance.

81%within 10 km at file start
3.0 kmmedian miss at file start
15cycles kept
15 of 15anchored in bitcoin

Headline figures from cycle a39dfdfee0fd, scored 2026-09-03 21:54 UTC, measured at the first instant of each operator file. Archive figures as of 2026-09-03 22:00 UTC.

What the public catalogue can see

At the first instant of each operator file, the public catalogue puts 81% of the scored Starlink satellites within 10 km of where the operator says they are. The middle satellite is 3.0 km away, with the public information a median of 13 hours old. Where the public information is two to three days old, the two predictions are about 25 km apart. Both sides are predictions, and most of that spread is planned trajectory changes the public catalogue cannot know about.

Everyone outside SpaceX sees Starlink through the public catalogue of orbital elements. Ephemera takes that public element set for each satellite, propagates it with SGP4, and compares it against the operator's own published trajectory for the same satellite at the same instants. The distance between the two is what this section measures. It is not an error of the satellite, and it is not a statement about which side is right.

41 satellites (0.4%) are more than 1,000 km from the public prediction at publication, which is a large part of an orbit. For those the public element set is not on the operator's trajectory at all. Ephemera does not label any separation as a manoeuvre; that needs a detector this project has not built.

Latest scored cycle a39dfdfee0fd, first seen 2026-09-03 12:09 UTC, scored 2026-09-03 21:54 UTC against the public catalogue snapshot fetched 2026-09-03 10:10 UTC (12,811 element sets). See it on the globe: every satellite drawn twice, the operator trajectory and the public catalogue's ghost.

1 km3 km10 km30 km1.40-6 h7482.46-12 h5,1494.612-24 h17,31810.924-48 h42,74024.848-72 h43,75639.6over 72 h33,496
Median separation between the two predictions, by how old the public catalogue's information was. Log scale; the second line under each point is how many comparisons it holds. Cycle a39dfdfee0fd, scored 2026-09-03 21:54 UTC.
The same curve as numbers, for cycle a39dfdfee0fd.
element agecomparisons median km90th pct km within 10 kmwithin 30 km
0-6 h7481.412.388%99%
6-12 h5,1492.413.986%96%
12-24 h17,3184.625.675%91%
24-48 h42,74010.974.648%80%
48-72 h43,75624.8220.735%54%
over 72 h33,49639.6234.227%46%

Element age is how old the public catalogue's information was at the instant compared. It runs larger than catalogue staleness because a single operator file predicts three days ahead, so a comparison late in the file is both further ahead and matched against an older element set. The two effects are not separated within one cycle, which is why the headline above uses only the first instant of each file.

By altitude shell

Same comparisons, split by where the satellite is. The lowest shell is where satellites are being raised and lowered, so its spread is the widest.
shellcomparisonsmedian kmwithin 10 km
under 400 km14,148102.525%
400-500 km117,66613.044%
500-600 km11,3934.767%

Feed health for this cycle. 11,090 of 11,117 operator files scored. 27 have no entry in the public catalogue, of which 27 are new satellites the catalogue has not numbered yet; 0 marked decayed; 0 failed to propagate; 0 unreadable. Public element sets were a mean of 15.1 h old when the snapshot was taken (median 12.3 h, 90th percentile 27.6 h, 26 over 72 h). Averaged over every comparison, which run out to three days into the operator file, element age is 51.2 h: the difference is the file's own prediction horizon, not catalogue staleness. Space-Track: 12 snapshots held, last fetched 2026-09-03 20:10 UTC with 12,811 element sets. Poller heartbeat coverage over the last 24 h: 100.0%.

Every scored cycle

One row per cycle, measured at the first instant of each file so the rows are comparable. Newest first.
cycle first seencycle scoredpairing median age hmedian km within 10 kmlost
2026-09-03 12:09a39dfdfee0fd11,090scored live12.63.081%41
2026-09-03 04:131e726fe006d911,091scored live20.54.673%43
2026-09-02 22:54b37c74c0390710,655scored live15.33.480%39
2026-09-02 20:153572d877591311,091scored live12.52.785%38
2026-09-02 12:08f5112bb77a2a11,091scored with hindsight4.51.591%33
2026-09-02 04:120a85a65d5dbe11,091scored with hindsight-3.41.391%32
2026-09-01 23:2451d5c047650a10,901scored with hindsight-8.31.290%42
2026-09-01 20:097414ea02eac111,048scored with hindsight-11.41.189%80

Showing the 8 most recent of 11 scored cycles; the rest are in ledger.json. A cycle marked scored with hindsight was matched against a catalogue snapshot fetched after it, because the cycle predates this project's catalogue feed. Its element sets already know what the satellite did during the file, so its numbers look better than they should and are not comparable with the rest. 7 of 11 scored cycles are in that state, and the count only falls from here.

How this was measured

Public element set (Space-Track gp snapshot) propagated with SGP4 (skyfield 1.55, python-sgp4 2.27; TEME to GCRS by Skyfield, taken as J2000) and differenced against the operator-published trajectory (EME2000) at the file's own record epochs every 360 min. Distance in km; components in the operator's radial/in-track/cross-track frame; altitude is geocentric radius minus 6378.137 km; element age is evaluation epoch minus element-set epoch, signed. A comparison beyond 1000 km is counted as lost: the public set is not on the file's trajectory at all. at_file_start takes each satellite once, at the first epoch of its own file, which is the only cut comparable between cycles. Both inputs are predictions; the operator's includes planned trajectory changes the public set cannot know about.

Snapshot 20260903T101011Z_ff964e6b31f2. Evaluation every 360 minutes across each file's own record epochs. Public element sets come from Space-Track.org and are redistributed under Space-Track's blanket approval for basic space situational awareness data, with citation.

The archive behind it

The operator side of every comparison above comes from files this project caught before they were replaced. Each cycle is hashed file by file into one Merkle root, the root is stamped into the Bitcoin blockchain through OpenTimestamps, and the manifest plus ten files chosen by the root itself are pushed into the Wayback Machine so an independent copy exists that this project does not control.

As of 2026-09-03 22:00 UTC: 15 cycles, 15 complete with roots, 15 anchored in Bitcoin, 7 with a defect in the independent copy. Source bytes archived: 336 GB across 165,776 files as served. Stored gzipped as 138 GB, of which 92 GB is on the poller's disk and 46 GB exists only in cold object storage. Cadence holds, meaning a set served longer than nine hours: 1. Poller heartbeat coverage over the last 24 hours: 100.0%. This project exists because SpaceX publishes the feed openly.

31 Aug01 Sep02 Sep03 Sepa39dfdfee0fd first seen 2026-09-03 12:09 UTC, 11,117 files1e726fe006d9 first seen 2026-09-03 04:13 UTC, 11,118 filesb37c74c03907 first seen 2026-09-02 22:54 UTC, 10,682 files3572d8775913 first seen 2026-09-02 20:15 UTC, 11,118 filesf5112bb77a2a first seen 2026-09-02 12:08 UTC, 11,092 files0a85a65d5dbe first seen 2026-09-02 04:12 UTC, 11,093 files, the archived manifest copy is another cycle's file51d5c047650a first seen 2026-09-01 23:24 UTC, 10,902 files7414ea02eac1 first seen 2026-09-01 20:09 UTC, 11,093 files, the archived manifest copy is another cycle's file7be3c2c6fc2c first seen 2026-09-01 12:26 UTC, 11,094 filesd03dc522da18 first seen 2026-09-01 02:22 UTC, 11,093 files, 6 of 10 sample captures were lost513b92c4683e first seen 2026-08-31 20:22 UTC, 10,481 files, the manifest was never captured1d424255c9ae first seen 2026-08-31 11:44 UTC, 8,568 files5e4faf0f4e4e first seen 2026-08-31 04:09 UTC, 9,353 files, no independent copy was made92e6892c0f3e first seen 2026-08-30 20:02 UTC, 9,111 files, no independent copy was made72bcd7796b49 first seen 2026-08-30 13:32 UTC, 17,861 files, no independent copy was made
Every cycle kept, on a time axis. Green is complete and independently copied, grey is complete with the copy still pending, amber is complete but the independent copy failed, red is an incomplete pull. Gaps in the spacing are the feed's own cadence. As of 2026-09-03 22:00 UTC.
The most recent 15 cycles. Amber marks a cycle whose own pull succeeded but whose independent copy did not.
first seen (utc)cycle filessource gb merkle rootopentimestamps wayback machineheld
2026-09-03 12:09a39dfdfee0fd11,11722.67ff9f56e1cc1block 965318manifest ok, 10/10 samples verifiedspool and cold storage
2026-09-03 04:131e726fe006d911,11822.5449b43de57fablock 965263manifest ok, 10/10 samples verifiedspool and cold storage
2026-09-02 22:54b37c74c0390710,68221.73b31bf7689b6block 965241manifest ok, 10/10 samples verifiedspool and cold storage
2026-09-02 20:153572d877591311,11822.5e84216948e7bblock 965229manifest ok, 10/10 samples verifiedspool and cold storage
2026-09-02 12:08f5112bb77a2a11,09222.5b46aca785a05block 965172manifest ok, 10/10 samples verifiedspool and cold storage
2026-09-02 04:120a85a65d5dbe11,09322.5381a895ce84eblock 965124manifest COPY DOES NOT MATCH (the archived copy is another cycle's manifest), 10/10 samples verifiedspool and cold storage
2026-09-01 23:2451d5c047650a10,90222.2b0f2521600e2block 965103manifest ok, 10/10 samples verifiedspool and cold storage
2026-09-01 20:097414ea02eac111,09322.558ba872f5507block 965085manifest COPY DOES NOT MATCH (the archived copy is another cycle's manifest), 10/10 samples verifiedspool and cold storage
2026-09-01 12:267be3c2c6fc2c11,09422.54d03a6f8fe32block 965040manifest ok, 10/10 samples verifiedspool and cold storage
2026-09-01 02:22d03dc522da1811,09322.55d69cd6dc0c9block 964976manifest ok, 4/10 samples verified, 6 lostspool and cold storage
2026-08-31 20:22513b92c4683e10,48121.3476705cfc526block 964940manifest NEVER CAPTURED, 0/10 samples verified, 10 lostcold storage only
2026-08-31 11:441d424255c9ae8,56817.46df13e066f37block 964903manifest ok, 10/10 samples verifiedcold storage only
2026-08-31 04:095e4faf0f4e4e9,35319.091ca361b797ablock 964904no independent copy: cycle superseded before witnessing completed: 1 manifest + 10 sample captures never madecold storage only
2026-08-30 20:0292e6892c0f3e9,11118.58c653747b19ablock 964904no independent copy: cycle superseded before witnessing completed: 1 manifest + 10 sample captures never madecold storage only
2026-08-30 13:3272bcd7796b4917,86136.2677d3043ef28block 964904no independent copy: cycle superseded before witnessing completed: 1 manifest + 10 sample captures never madecold storage only

Method: built from each cycle's cycle.json, witness.json and ship.json in the poller's spool; coverage is the fraction of the last 24 h's minutes with a watcher heartbeat under 10 minutes old (D18); a cadence hold is a manifest first-seen gap over 9 h; source bytes are the responses as served, stored bytes are the gzipped archive objects the shipper recorded. Poller: home (Cape Town, residential; single poller until poller A exists).

Daily roots

A root over each day's complete cycle roots, built shortly after midnight UTC and stamped separately.
daterootleaves opentimestampsnote
2026-09-02647c6951a21d4block 965241none
2026-09-017ecb7906d01b3block 965103excluded 51d5c047650a (still pulling when the root was built)
2026-08-31948ecce3337d3block 964963none
2026-08-301d7acc715f622block 964927none

A cycle still pulling at midnight is left out of that day's root and stays out. It keeps its own cycle root and its own OpenTimestamps proof, so nothing is unwitnessed, but it sits under no daily root.

Check it yourself

None of this is worth anything if you have to take my word for it. Here is what you can run right now, and what still needs data this site does not publish yet. I would rather say which is which.

Fetch an independent copy and hash it. Each cycle's file list is pushed into the Wayback Machine the moment it is caught, so a copy exists that I do not control. For cycle a39dfdfee0fd that copy is here, and its SHA-256 is a39dfdfee0fd8f1a8a068e22d8428966a87b19c19d98721ba012192a60911d5e. Download it, hash it, and you have checked that the list of files I claim to have caught is the list the source was actually serving. Ten files from each cycle are copied the same way, and every copy URL and digest is in ledger.json.

Check which ten files were copied. I do not get to choose them. File number int(sha256(root + ":" + k), 16) mod n for k from 0 to 9, where n is the number of files in the list you just downloaded. Run that and you get the same ten names this site published.

Check the timestamp. Each cycle root is stamped through OpenTimestamps. Running ots verify root.txt.ots against a Bitcoin node shows this cycle's root committed in block 965318, which fixes the latest moment it could have been written. Nobody, including me, can move a root backwards once it is in a block. The proof files ship with the data release.

What you cannot do from this page alone is rebuild the Merkle root, because that needs the SHA-256 of every one of the 11,117 files in the cycle and this site publishes the summary rather than the full digest list. Those digests, and the exact byte format of the root file, come with the data release described below. The construction is the plain one: leaves are the file digests in manifest order, adjacent pairs are hashed as SHA-256 of the two digests joined end to end, and an odd trailing node is paired with a copy of itself.

Data, licence and citation

Licence. Code is MIT. Figures derived by this project are intended for CC BY 4.0. The raw SpaceX files carry no stated licence; a written request went to SpaceX on 31 August 2026 and is unanswered as of this build, and any file comes down on request. Public element sets come from Space-Track.org and are redistributed under Space-Track's blanket approval for basic space situational awareness data, with citation.

Citation. Ryan, K. (2026). Ephemera: an archive of the public Starlink ephemerides and a daily measure of public catalogue visibility. https://ephemera.space, retrieved 2026-09-03 22:00 UTC.

Not here yet

4 days of archive is not a long record, and this page should not pretend otherwise. What is running: the poller, the hashing, the witnessing, cold storage, and the catalogue comparison above. What is not:

Who runs this

Kira Ryan, on my own time, on a home computer in Cape Town, with no funding and no affiliation to any operator or agency. If a figure here is wrong I want to know, and corrections get published rather than quietly fixed.

KiraRyan27@gmail.com   linkedin.com/in/kira-ryan