Compare
Different libraries make different choices. This page sets GPKit's beside those of other Swift and Python libraries that run SGP4, as each project describes itself. It's about approach, not quality: each library is good at what it sets out to do.
For test results across many libraries, see gpconf's own pages, where each count is a result against one version on one date, not a verdict on the project.G-25
At a glance
| GPKit 1.0.0 | SatelliteKit 2.1.2 | python-sgp4 2.27 | Skyfield 1.55 | |
|---|---|---|---|---|
| Language | Swift | Swift | Python, with compiled C++ (and a pure-Python fallback) | Python |
| Licence | MIT | MIT | MIT | MIT |
| Dependencies | none | none (uses Foundation) | none required; NumPy for the array API | certifi, jplephem, numpy, sgp4 |
| SGP4 | a Swift transcription of Vallado's SGP4.cpp | derived from Orekit, following Vallado et al.'s 2006 paper and code | compiles Vallado's official C++ | uses python-sgp4 |
| TLE / 3LE | ✓ | ✓ | ✓ | ✓ |
| OMM CSV | ✓ | not in its docs (2.1.2, checked 2026-10-31) | ✓ | through python-sgp4's OMM support |
| OMM JSON | ✓ | ✓ | ✓ | through python-sgp4's OMM support |
| OMM XML | ✓ | ✓ | ✓ | through python-sgp4's OMM support |
| OMM KVN | ✓ | not in its docs (2.1.2, checked 2026-10-31) | not in its docs (2.27, checked 2026-10-31) | not in its docs (1.55, checked 2026-10-31) |
| Catalog number held as | Int, 0 to 999,999,999 |
UInt (noradIndex) |
integer satnum, and a 5-character satnum_str |
model.satnum, from python-sgp4 |
| Alpha-5 in TLEs | decoded on the way in; written by the TLE writer | decoded | supported, up to 339999 | through python-sgp4 |
| Gravity constants | WGS-72 default; WGS-84, WGS-72-old selectable | WGS-72 | WGS-72 default; WGS-72-old, WGS-84 selectable | python-sgp4's |
| Pass finding | ✓ rise, culmination, set | not in its docs (2.1.2, checked 2026-10-31) | not in its docs (2.27, checked 2026-10-31); it gives positions and points to Skyfield | ✓ rise, culminate, set |
| Look angles | ✓ | ✓ azimuth, elevation, distance | not in its docs (2.27, checked 2026-10-31) | ✓ |
| Doppler | ✓ downlink and uplink | not in its docs (2.1.2, checked 2026-10-31) | not in its docs (2.27, checked 2026-10-31) | not in its docs (1.55, checked 2026-10-31) |
| Sunlit check | none: GPKit has no sun model | sun and moon positions | not in its docs (2.27, checked 2026-10-31) | ✓ |
| Platforms | macOS 13, iOS 16, tvOS 16, visionOS 1, Linux | macOS 11, iOS 12, tvOS 12, watchOS 10, visionOS 2 | Python 2.7, 3.10–3.14 | Python 2.7, 3.7–3.13 |
| How it says it's checked | against the C++ compiled as it is, within 1 micrometre; Skyfield; python-sgp4; gpconf | agrees with Orekit's test output and the paper's | passes the automated tests of Vallado et al.'s 2010 reference release | not in its docs (1.55, checked 2026-10-31) |
"Not in its docs" means the project's own documentation, at the version named and on the date checked, doesn't describe it. It doesn't mean the project can't do it.
C-01–C-04 for each column; GPKit's fromK-02K-04K-24K-30K-31K-40K-42K-43K-55K-60K-82.
The choices, in words
Catalog numbers. GPKit holds every catalog number as an Int and keeps Alpha-5 only in a TLE's five columns.K-24
SatelliteKit holds it as a UInt and decodes Alpha-5.C-02 python-sgp4 gives an integer satnum and a 5-character
satnum_str, and supports Alpha-5.C-03
Where SGP4 comes from. GPKit transcribes Vallado's SGP4.cpp into Swift, statement for statement, and tests the transcription against the C++ compiled as it is.K-30K-40 python-sgp4 compiles Vallado's C++ itself, and Skyfield builds on python-sgp4.C-03C-04 SatelliteKit is derived from Orekit's implementation of the same published algorithms.C-02
What's in the box. python-sgp4 returns positions and velocities in TEME and leaves frame conversions to libraries
like Skyfield.C-03 Skyfield adds observers, rise and set, and sunlight.C-04 GPKit and SatelliteKit both include
look angles. GPKit adds a pass search and Doppler, and 1.0.0 leaves out the sun; GPKit's main, not yet in a release, adds a sun
model.K-55K-60C-02K-96
Formats. GPKit reads OMM in CSV, JSON, XML and KVN, and TLE, all into one record type.K-22K-12
One public report, cited with permission
In a public comment on python-sgp4's issue #173, the owner of GPKit and gpconf showed that python-sgp4 2.27's
from_alpha5('A+123') and from_alpha5('A1_23') both return 100123, because the digits after the letter are read
with int().X-01 GPKit's Alpha-5 decoder refuses a sign or any character but a digit after the letter, and a
test on main checks it on A+123 and A1_23.K-23K-103
Read the comment →
Sources
G-25"a count is a result against that version on that date, not a verdict on the project". Source: gpconf:README.md:242.C-01GPKit's column of the table. Source: the K- claims cited under the table.C-04Skyfield 1.55: Python, MIT; requires certifi, jplephem, numpy, sgp4; wraps python-sgp4; TLE files (with name line) andfrom_omm;find_events(rise, culminate, set);altaz;is_sunlit; Python 2.7, 3.7–3.13; no satellite Doppler or KVN described. Source: installedskyfield-1.55.dist-info/METADATA:3-27;skyfield/sgp4lib.py:2-8,141-151,215-216;skyfield/positionlib.py:314,570-571;skyfield/iokit.py:428-436.K-02A Swift package with no dependencies: OMM (CSV, JSON, XML, KVN) and TLE readers, a TLE writer, SGP4, passes with look angles and Doppler. Source: GPKit:README.md:17-18;Package.swift:14.K-04Platforms: macOS 13, iOS 16, tvOS 16, visionOS 1. Linux is built in CI. Source: GPKit:Package.swift:9;.github/workflows/ci.yml:16.K-24Catalog numbers are an Int; OMM NORAD_CAT_ID takes up to nine digits; Alpha-5 is refused in OMM. Source: GPKit:OMM.swift:4-17;ElementSet.swift:9-10;OMMTests.swift:58-70.K-30SGP4 is a port of Vallado's SGP4.cpp (CelesTrak/fundamentals-of-astrodynamics 49df0479c950), with names and order of operations kept. Source: GPKit:NOTICE:9-17;SGP4Core.swift:1-15.K-31Gravity constants WGS-72 (default), WGS-84 and WGS-72-old. Source: GPKit:SGP4Core.swift:78-108;Propagator.swift:76-94.K-40SGP4 vs the unmodified C++: 33 cases (24 deep space), 2,349 steps, equal error codes, agreeing within 1 micrometre (asserted). Source: GPKit:SGP4Tests.swift:74-75,102-126.K-42Skyfield 1.55: five public element sets over 40° N, 75° W, two days each; 49 passes; 95 rises and sets within 0.166 s; 47 culminations within 0.349 s; look-angle bounds. Source: GPKit:conformance/skyfield-2026-10-07.txt:1-19; testPassTests.swift:168-248.K-43python-sgp4 2.27: 14,411 element sets, 86,466 states (0, 90, 720, 1,440, 4,320 and 10,080 min), largest difference 0.0024 mm, no differing error codes. Not run in CI. Source: GPKit:conformance/python-sgp4-crosscheck-2026-10-07.txt:5-10;CrossCheckTests.swift:5-14.K-55GPKit has no sun or visibility model and no azimuth-dependent horizon. Source: GPKit: a grep of Sources for sun/eclipse/sunlit/twilight found nothing; signaturepasses(over:from:for:above:).K-60Doppler: received = f(1 − ṙ/c), transmit = f/(1 − ṙ/c), c = 299,792.458 km/s. Source: GPKit:Observer.swift:75-88.K-82CI runs gpconf's 5 offline cases; 13 need provider files that gpconf fetches and does not ship. Source: GPKit:README.md:153-155;ci.yml:33-56;tools/check_gpconf.py.C-02SatelliteKit 2.1.2: Swift, MIT, no dependencies; TLE/3LE, JSON and XML GP data;noradIndex: UInt; Alpha-5 decoded; derived from Orekit, after Vallado et al. 2006; WGS-72 constants;topPositiongives azimuth, elevation, distance; sun and moon positions; macOS 11, iOS 12, tvOS 12, watchOS 10, visionOS 2; checked against Orekit's and the paper's test output. CSV, KVN, pass finding and Doppler not described. Source: local clone~/Developer/satkit-pr17-check/repoat tag 2.1.2 (9a87cdb, 2026-06-02):README.md:4,10-13,91,103,144,340,345;Package.swift:1-9,18;LICENSE:1-3;Sources/SatelliteKit/TLE/Propagator.swift:28-40;Astro/Geography.swift:187;Astro/Astronomy.swift:82,118; greps for csv, kvn, doppler, passes: none.C-03python-sgp4 2.27: compiles Vallado's official C++ (2023 May 09 release), pure-Python fallback; MIT; TLE and OMM (CSV, JSON, XML; KVN not described); integersatnumand 5-charactersatnum_str; Alpha-5 supported to 339999; WGS-72 default, WGS-72-old and WGS-84 selectable; TEME positions only, pointing to Skyfield for conversions; passes Vallado et al.'s 2010 reference tests; Python 2.7, 3.10–3.14. Source: installedsgp4-2.27.dist-info/METADATA:3-18,32-37,56-58,66-76,182-185,200-230,502-503,645-646;sgp4/alpha5.py:1-8;sgp4/omm.py:1-29.K-96Sun(the sun's position and height at a place, after the NOAA calculators' formulas),Sunlight(the sky at a place: daylight, twilight or dark; whether the satellite is sunlit; phase angle; a brightness estimate) andPassVisibility(when in a pass the satellite is sunlit and when it can be seen with the eye). Source: GPKit main 11b7ab4 (PR #25, 2026-11-07):CHANGELOG.md:24-29;docs/public-api.swift:288,:301,:317,:331.K-22OMM in CSV, JSON, XML (505.0-B-3) and KVN (502.0-B-3 §7). Quirks handled as listed. DOCTYPE refused. Source: GPKit:ElementSets.swift:1-13;XML.swift:1-7;README.md:105-119.K-12One record type whatever the format; "the TLE is a way in, not the model". Source: GPKit:ElementSet.swift:3-4;README.md:64-65.X-01In a public comment on python-sgp4 #173,from_alpha5('A+123')andfrom_alpha5('A1_23')both return 100123, because the digits after the letter are read withint(). Source: https://github.com/brandon-rhodes/python-sgp4/issues/173#issuecomment-6460454893 (hneogy, 2026-10-28T04:11:27Z), read through GitHub's API on 2026-10-31.K-23Alpha-5 as Space-Track defines it: A–Z without I and O = 10–33, ceiling 339999. Test vectors. Source: GPKit:Alpha5.swift:1-46;ValueTests.swift:85-101.K-103GPKit's Alpha-5 decoder refuses a sign or any character but a digit after the letter (the same guard in 1.0.0 and onmain); a test onmain, not yet in a release, checks thatA+123andA1_23are refused, by the decoder and by the TLE reader. Source: GPKit main 11b7ab4 (PR #25, 2026-11-07):CHANGELOG.md:76(under "Unreleased");Tests/GPKitTests/TLETests.swift:38-47(aSignOrAnUnderscoreAfterTheLetterIsRefused);Sources/GPKit/Alpha5.swift:26, identical at v1.0.0.