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

  1. G-25 "a count is a result against that version on that date, not a verdict on the project". Source: gpconf: README.md:242.
  2. C-01 GPKit's column of the table. Source: the K- claims cited under the table.
  3. C-04 Skyfield 1.55: Python, MIT; requires certifi, jplephem, numpy, sgp4; wraps python-sgp4; TLE files (with name line) and from_omm; find_events (rise, culminate, set); altaz; is_sunlit; Python 2.7, 3.7–3.13; no satellite Doppler or KVN described. Source: installed skyfield-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.
  4. K-02 A 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.
  5. K-04 Platforms: macOS 13, iOS 16, tvOS 16, visionOS 1. Linux is built in CI. Source: GPKit: Package.swift:9; .github/workflows/ci.yml:16.
  6. K-24 Catalog 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.
  7. K-30 SGP4 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.
  8. K-31 Gravity constants WGS-72 (default), WGS-84 and WGS-72-old. Source: GPKit: SGP4Core.swift:78-108; Propagator.swift:76-94.
  9. K-40 SGP4 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.
  10. K-42 Skyfield 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; test PassTests.swift:168-248.
  11. K-43 python-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.
  12. K-55 GPKit has no sun or visibility model and no azimuth-dependent horizon. Source: GPKit: a grep of Sources for sun/eclipse/sunlit/twilight found nothing; signature passes(over:from:for:above:).
  13. K-60 Doppler: received = f(1 − ṙ/c), transmit = f/(1 − ṙ/c), c = 299,792.458 km/s. Source: GPKit: Observer.swift:75-88.
  14. K-82 CI 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.
  15. C-02 SatelliteKit 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; topPosition gives 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/repo at 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.
  16. C-03 python-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); integer satnum and 5-character satnum_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: installed sgp4-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.
  17. K-96 Sun (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) and PassVisibility (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.
  18. K-22 OMM 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.
  19. K-12 One record type whatever the format; "the TLE is a way in, not the model". Source: GPKit: ElementSet.swift:3-4; README.md:64-65.
  20. X-01 In a public comment on python-sgp4 #173, from_alpha5('A+123') and from_alpha5('A1_23') both return 100123, because the digits after the letter are read with int(). 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.
  21. K-23 Alpha-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.
  22. K-103 GPKit's Alpha-5 decoder refuses a sign or any character but a digit after the letter (the same guard in 1.0.0 and on main); a test on main, not yet in a release, checks that A+123 and A1_23 are 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.