Satellite.js

SGP4/SDP4 satellite propagation library for computing orbital position and velocity from TLEs or OMM in JavaScript.

Library
npm
v7.1.0
1,077stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
71/100Good
Development Activity64
Maintenance56
Community76
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
84/100Excellent
Architecture85
Code Quality88
Innovation84
Learning Curve78

Satellite.js is a modular TypeScript library that implements the SGP4 and SDP4 orbit propagation models used to compute a satellite’s position and velocity from Two-Line Element sets (TLEs) or Orbit Mean-Elements Messages (OMM). It ports the well-known Vallado/Kelso reference implementation of SGP4 so that satellite tracking, ground-station look-angle calculations, and orbital visualization can run directly in the browser or in Node.js without a native binary dependency.

Beyond raw propagation, the library provides the supporting coordinate-transform pipeline needed to turn a raw ECI position into something usable: ECI-to-ECF, ECI-to-geodetic, look angles (azimuth/elevation/range) from an observer, Doppler factor, GMST/Julian date conversions, sun position, and eclipse/shadow-fraction calculations. A newer WASM-backed bulk propagation API compiles the same C++-derived math to WebAssembly for 3x-12x throughput when propagating many satellites across many timestamps, while the pure-TypeScript API remains the default for single-satellite use.

What You Get

  • SGP4/SDP4 propagation via twoline2satrec/json2satrec (TLE or OMM input) plus sgp4/propagate to get ECI position and velocity for a given time
  • A full coordinate-transform toolkit: ECI/ECF conversions, geodetic conversion, look angles (azimuth, elevation, range), and GMST/Julian-date helpers
  • Doppler factor, sun position, and shadow-fraction (eclipse) calculations for downlink and visibility modeling
  • An opt-in community decay check (checkForDecay) that filters satellites SGP4 reports as ‘successful’ but whose long-decayed elements produce meaningless positions
  • A WASM-backed BulkPropagator API for propagating large satellite catalogs across many timestamps 3x-12x faster than the JS loop
  • Full TypeScript types for every input/output shape, published as ESM with no runtime dependencies

Common Use Cases

  • Satellite tracking dashboards and ground-station pass predictors that plot real-time position from public TLE catalogs (e.g. CelesTrak, Space-Track)
  • 3D orbital visualization tools (Cesium, Three.js) that need ECI/geodetic coordinates per frame
  • Amateur radio and ground-station scheduling software computing look angles and Doppler shift for a pass
  • Bulk catalog processing — e.g. propagating thousands of tracked objects across a time window for conjunction or visibility screening

Under The Hood

Architecture: The library separates concerns into a small number of focused modules under src/: io.ts parses TLE strings or OMM JSON into a SatRec state object via sgp4init; propagation/ holds the actual SGP4/SDP4 numerical routines (sgp4.ts, dpper.ts, dscom.ts, dsinit.ts, dspace.ts, initl.ts) ported near-verbatim from the Vallado/Hoots reference implementation to ease auditing against future algorithm corrections; transforms.ts and sun.ts/shadow.ts layer coordinate conversions and illumination math on top of the raw ECI output; and src/wasm/ provides a parallel BulkPropagator execution path with per-quantity ‘calculators’ (ECF position/velocity, geodetic, look angles, Doppler, sun position, shadow fraction) that read/write directly into WASM linear memory (struct-read.ts/struct-write.ts) to avoid per-call marshaling overhead. propagate() is a manually-overloaded function that accepts either a Date or explicit year/month/day/hour/minute/second/ms arguments plus an optional PropagateOptions, delegating to jday and sgp4.

Tech Stack: Pure TypeScript (64% of the codebase) for the public API and core SGP4 math, with a C++ core (src-cpp/SGP4.cpp, base.cpp, pthreads.cpp) compiled via Emscripten (em++) into single-file WASM modules for the bulk-propagation path, built in both single-threaded and pthreads (ASYNCIFY, PTHREAD_POOL_SIZE_STRICT=0) variants with debug (AddressSanitizer/LeakSanitizer-instrumented) and release (-O3, SIMD128) builds. The package ships ESM-only (type: module, single exports entry) with zero runtime dependencies; TypeScript 7 and Biome handle typechecking/linting, and Vitest runs multiple test ‘projects’ (js, wasm_release, wasm_debug, catalog).

Code Quality: Test coverage is unusually thorough for a small library: unit tests per module (ext, io, transforms, sun, shadow, dopplerFactor), dedicated propagation-internals tests (dsinit.test.ts, initl.test.ts), a full sgp4Catalog.test.ts that replays a real TLE catalog against golden sgp4CatalogResults.json output to catch any regression in the numerical output, WASM-specific leak/struct/type-definition tests, and test:types running tsc --noEmit against a dedicated type-tests project. Public functions consistently validate input ranges (e.g. degreesLat/radiansLong throw RangeError outside valid bounds) and surface propagation failures through a typed SatRecError enum rather than silent nulls. Comments throughout the SGP4 internals preserve the original FORTRAN-derived variable naming and structure deliberately, to keep the port auditable against Vallado’s published corrections rather than optimizing for idiomatic TypeScript style.

API Design: The public surface is a small, flat set of named exports (twoline2satrec, propagate, sgp4, coordinate-transform functions) re-exported from a single index.ts, so getting from a TLE string to a look-angle result is a handful of direct function calls without classes to instantiate or config objects to assemble, beyond optional PropagateOptions. Overloaded propagate() signatures let callers pass either a Date or discrete date components, and every physical quantity (Radians, Degrees, Kilometer, EciVec3<T>) is branded in the type system to prevent unit-mismatch bugs at compile time. The README’s quick-start walks through the full TLE-to-look-angles pipeline in one contiguous example, and a dedicated Docusaurus docs site covers OMM input, bulk propagation, and the community decay-check option in depth.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search