lxephemeris
The modern astronomical & astrological computation engine for Python, Node.js, and Rust.
100% memory-safe Rust core (#![forbid(unsafe_code)]). Lock-free multi-threading. Zero external files required to start — with native NASA JPL DE440s support for < 0.003" precision.
import lxephemeris
# Works out of the box with zero external files (or loads NASA JPL DE440s if present)
engine = lxephemeris.Engine()
jd_utc = lxephemeris.utc_from_local(2026, 10, 27, 14, 30, 0.0, tz_name="America/New_York")
obs = lxephemeris.Observer(latitude_deg=40.7128, longitude_deg=-74.0060, altitude_m=10.0)
# Full natal snapshot: planets, 23 house systems, aspects, Hermetic lots, lunar phase & sect in ~150 µs
chart = engine.chart_snapshot(jd_utc, obs)
Why lxephemeris?
Legacy backends stitch together 30-year-old C bindings (pyswisseph), PyEphem, and Kerykeion — inheriting process-global mutable C state, thread race conditions, silent polar house errors, and slow FFI loops. lxephemeris replaces the entire stack with a single clean-room Rust engine:
- One Engine Replaces 6+ Libraries: Ships 10 planets, 68 JPL minor bodies (
Chiron,Ceres,Eris,Sedna,Lilith (1181)...), 7 Lunar nodes/apogees, 9 Uranians, 23 house systems (with explicit polar policies), 43+1 sidereal ayanamsas, 52 Hipparcos-2/XHIP fixed stars, solar/lunar eclipses & occultations, Vedic Panchanga / 16 Vargas / Vimshottari Dasha, Traditional Sect / Planetary Hours / 7 Hermetic Lots, Human Design 64 Gates &-88°arc, 24 Chinese Solar Terms (Jieqi), and native Transit / Return / Station / VoC Moon solvers. - Lock-Free Thread Safety & Memory Safety:
#![forbid(unsafe_code)],Send + Sync, zero global C state, zero locks required across concurrent Tropical, Sidereal, and Topocentric requests. - 5–15× Faster: Single-pass analytical velocity Jacobians (
12.8 µs/body with speed;~150 µs/full natal chart) + GIL-free Rayon multi-core batching. - 22 Upstream Bugs Eliminated: Fixes global C races,
±66°latitude clamps (7.85° Svalbard ASC error),Mira/Mirachstar collisions, star-anchor aberration wobble, andSun().hlong$180^\circ$ inversions. - Drop-In
SweAdapter: Migrate existingpyswissephcodebases in minutes without rewriting call sites.
👉 Read the full architectural deep-dive & 22 eliminated legacy bugs →
☁️ Want a Turnkey Cloud API Instead of Self-Hosting?
lxephemeris is the low-level astronomical & astrological math engine that powers AstroAPI (astrology-api.io) and Astrolium (astrolium.com).
If you are building a commercial astrology app, SaaS, or mobile product and don't want to maintain your own ephemeris infrastructure — or purchase a self-hosted commercial engine license — use AstroAPI directly:
- Turnkey REST API powered by
lxephemerisin production - Built-in City Geocoding & Historical Timezone / DST Resolution (
birth city + date/time→ full chart) - SVG Chart Wheel Rendering, Synastry Compatibility Scoring, and Structured Interpretations
- Commercial Rights Included: Your AstroAPI subscription includes commercial production usage — no separate
lxephemeriscommercial license required.
How lxephemeris Compares
| Feature | lxephemeris |
Swiss Ephemeris (pyswisseph) |
Kerykeion | PyEphem (ephem) |
Skyfield |
|---|---|---|---|---|---|
| Core Architecture | 100% Safe Rust (#![forbid(unsafe_code)]) |
Legacy C (libswe, 1990s) |
Python wrapper over pyswisseph |
Legacy C (libastro) |
Pure Python / NumPy |
| Thread Safety | Lock-free Send + Sync (0 state bleed) |
❌ Global mutable C static state |
❌ Inherits pyswisseph globals |
⚠️ Mutable Body objects |
✅ Thread-safe |
| Works with 0 External Files | ✅ Built-in analytical engine (-3000..+3000) |
⚠️ Silent fallback if .se1 missing |
✅ Bundles .se1 files |
✅ Analytical only | ❌ Requires downloading .bsp |
JPL DE440s / DE441 Precision |
✅ Native DAF/SPK (< 0.003") |
Compressed .se1 re-fits |
Via pyswisseph |
❌ Truncated VSOP87 (multi-arcsec drift) | ✅ Native SPK |
| Single Body + Speed Latency | 12.8 µs (analytical Jacobian) |
~45–90 µs (3-pt finite diff) |
~25–80 ms per subject |
~80–150 µs |
~600–2,000 µs |
| 23 Houses & Arctic/Polar Safety | ✅ All 23 + explicit PolarPolicy |
⚠️ Silent polar fallback & house_pos=0.0 bug |
❌ Clamps |lat| > 66° (7.85° ASC error) |
❌ No astrological houses | ❌ No astrological houses |
| 68 Astrological Minor Bodies | ✅ Single verified .bsp + Keplerian fallback |
Manage 68 separate .se1 files |
Partial | ❌ Manual orbital elements | Manual SPK segments |
| 43+1 Sidereal Ayanamsas | ✅ Aberration-free star anchors | ⚠️ ±20.5" annual aberration wobble on star anchors |
⚠️ Leaves secondary points tropical | ❌ None | ❌ None |
| Transit, Return & VoC Moon Solvers | ✅ Native Rust Newton-Illinois solvers | ❌ Write your own FFI loops | ❌ Static charts only | ❌ Basic rising/phase only | Discrete almanac only |
| Vedic (Panchanga, Dasha, D1–D60) | ✅ Built-in | ❌ None | ❌ None | ❌ None | ❌ None |
| Traditional (Sect, Hours, 7 Lots) | ✅ Built-in | ❌ None | ❌ None | ❌ None | ❌ None |
Human Design (64 Gates & -88° Arc) |
✅ Built-in | ❌ None | ❌ None | ❌ None | ❌ None |
| SDKs with Identical Math | Python, Node.js/TS, Rust, CLI | C + separate 3rd-party bindings | Python only | Python only | Python only |
Quickstart
Installation
# Python (PyPI)
pip install lxephemeris
# Node.js / TypeScript (npm)
npm install lxephemeris
# Rust Library & CLI (crates.io)
cargo add lxephemeris-core
cargo install lxephemeris-cli
Python (lxephemeris)
import lxephemeris
# 1. Start immediately (zero external files needed) or load NASA JPL DE440s from ./data
engine = lxephemeris.Engine()
# engine = lxephemeris.Engine.from_data_dir("./data", verify_manifest_sha256=True)
# 2. Local wall-clock time -> UTC Julian Date (preserves fractional seconds & PEP 495 DST fold)
jd_utc = lxephemeris.utc_from_local(2026, 10, 24, 14, 0, 32.5, tz_name="Europe/Berlin", fold=0)
obs = lxephemeris.Observer(51.5074, -0.1278, 35.0)
# 3. Single body position + analytical speed + visual magnitude
sun = engine.calc("Sun", jd_utc, scale="UTC")
chiron = engine.calc("Chiron", jd_utc, scale="UTC")
print(f"Sun: {sun.lon_deg:.6f}° (speed={sun.lon_speed_deg_day:.6f}°/d, Vmag={sun.magnitude_v:.2f})")
# 4. Polar-safe houses & cusp boundary guard (eps = 1e-9°)
houses = engine.houses(
jd_utc,
latitude_deg=51.5074,
longitude_deg=-0.1278,
system="P",
scale="UTC",
polar_policy="fallback_to_whole_sign",
)
sun_house = lxephemeris.house_of_lon(sun.lon_deg, houses.cusps_deg, eps_deg=1e-9)
# 5. All-in-one Natal Snapshot, Solar Return, Vedic Panchanga, & Human Design Gate
snapshot = engine.chart_snapshot(jd_utc, obs)
solar_return = engine.planetary_return("Sun", jd_utc, jd_utc + 350.0)
panchanga = engine.panchanga(jd_utc, obs, ayanamsa="lahiri")
hd = lxephemeris.map_zodiac_placement(sun.lon_deg)
print(f"ASC: {houses.asc_deg:.4f}° | Sun in House {sun_house} | HD Gate {hd.hd_gate}.{hd.hd_line}")
Node.js / TypeScript (lxephemeris)
import { Engine, utcFromLocal, houseOfLon, mapZodiacPlacement } from "lxephemeris";
const engine = new Engine();
// const engine = Engine.fromDataDir("./data", 4, null, true);
const jdUtc = utcFromLocal(2026, 10, 24, 14, 0, 32.5, "Europe/Berlin");
const jdSplit = { jd1: jdUtc, jd2: 0.0 };
const obs = { latitudeDeg: 51.5074, longitudeDeg: -0.1278, altitudeM: 35 };
const sun = engine.calc("Sun", jdSplit, "UTC");
const houses = engine.houses(jdSplit, obs, "P", "UTC", "fallback_to_whole_sign");
const sunHouse = houseOfLon(sun.lonDeg, houses.cuspsDeg, 1e-9);
const snapshot = engine.chartSnapshot(jdUtc, obs);
const hd = mapZodiacPlacement(sun.lonDeg);
console.log(
`Sun: ${sun.lonDeg.toFixed(6)}° in House ${sunHouse} | HD Gate ${hd.hdGate}.${hd.hdLine} | Lots: ${snapshot.lots.length}`
);
Rust (lxephemeris-core)
use lxephemeris_core::{
AspectPreset, BodyId, CalcOptions, Engine, HouseOptions, HouseSystem, Observer,
PlanetId, PolarPolicy, TimeInput, JD_J2000,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let engine = Engine::default();
let t = TimeInput::from_tt_jd(JD_J2000);
let sun = engine.calc(BodyId::Planet(PlanetId::Sun), t, CalcOptions::default())?;
let obs = Observer::new(51.5074, -0.1278, 35.0)?;
let houses = engine.houses(
t,
obs,
HouseOptions {
system: HouseSystem::Placidus,
polar_policy: PolarPolicy::FallbackToWholeSign,
..Default::default()
},
)?;
let snapshot = engine.chart_snapshot(
t,
obs,
&[BodyId::Planet(PlanetId::Sun), BodyId::Planet(PlanetId::Moon)],
HouseOptions::default(),
CalcOptions::default(),
AspectPreset::Major,
1.0,
)?;
println!("Sun={:.6}°, ASC={:.4}°, Lots={}", sun.lon_deg, houses.angles.asc_deg, snapshot.lots.len());
Ok(())
}
CLI (lxephemeris-cli)
lxephemeris-cli calc --jd 2460676.5 --bodies Sun,Moon,Chiron
lxephemeris-cli houses --jd 2460676.5 --lat 51.5074 --lon -0.1278 --system P
lxephemeris-cli panchanga --jd 2460676.5 --lat 28.6139 --lon 77.2090 --ayanamsa lahiri
lxephemeris-cli fetch-kernel --kernel de440s --data-dir ./data
Verification & Benchmarks
Verified against 37,416 golden reference vectors from NASA JPL Horizons (DE440 / SB441-N16), IAU SOFA, and USNO across 145+ Rust tests, 18 Python test suites, and 12 Node.js test suites (100% PASS). Single-body position + analytical velocity runs in 12.8 µs; a full natal chart runs in ~150–240 µs.
👉 Full Verification & Benchmark Report (ACCEPTANCE_REPORT.md) →
Documentation
- Why
lxephemeris& 22 Eliminated Legacy Bugs (docs/WHY_LXEPHEMERIS.md) — Architecture overview and legacy bug breakdown. - Quickstart & Complete API Guide (
docs/QUICKSTART_AND_API.md) — Full examples for Python, Node.js/TypeScript, Rust, and CLI. - Migration Guide from
pyswisseph,PyEphem&Kerykeion(docs/SWE_MIGRATION_GUIDE.md) — Side-by-side before/after migration patterns. - CLI Reference (
crates/lxephemeris-cli/README.md) — All subcommands and flags forlxephemeris-cli. - Intentional Divergences & Bug Proofs (
docs/SE_DIVERGENCES.md) — Mathematical proofs of all 22 upstream bug fixes. - Mathematical Model Passports (
docs/MODEL_PASSPORTS.md) — Equations, constants, and peer-reviewed citations. - Verification & Benchmark Report (
ACCEPTANCE_REPORT.md) — 37,416-vector verification metrics and latency benchmarks.
Licensing & Commercial Use
lxephemeris is dual-licensed (LICENSE.md). Choose the option that fits your deployment:
| Option | Best For | Commercial Rights | How to Start |
|---|---|---|---|
| ☁️ AstroAPI (Managed Cloud API) | Web/mobile apps, SaaS startups & teams wanting turnkey REST endpoints, city geocoding, SVG chart wheels & interpretations | ✅ Included in API subscription | Start at astrology-api.io → |
🏢 lxephemeris Commercial License (LicenseRef-Commercial) |
Self-hosted backends, high-throughput batch pipelines & on-premise services running lxephemeris on your own servers |
✅ Included via offline Ed25519 key (LXEPHEMERIS_LICENSE_KEY) |
Request License (procoders.tech/contacts) → or lxephemeris@procoders.tech |
🎓 lxephemeris Non-Commercial (PolyForm-Noncommercial-1.0.0) |
Personal projects, academic research, education, non-profits & 30-day pre-purchase commercial evaluation | ❌ Non-commercial & 30-day staging eval only | pip install lxephemeris / npm i lxephemeris |
👉 Full Dual-Licensing Policy & Offline Key Activation (LICENSE.md) →
Metadata
Release files for lxephemeris 1.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| lxephemeris-1.0.1.tar.gz | 371.0 kB | Without provenance | Details for lxephemeris-1.0.1.tar.gz |
Built distributions (wheels)
| File | Actions Reset | |||
|---|---|---|---|---|
| lxephemeris-1.0.1-cp39-abi3-win_amd64.whl | CPython 3.9 | abi3 | Windows x86-64 | Details for lxephemeris-1.0.1-cp39-abi3-win_amd64.whl |
| lxephemeris-1.0.1-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl | CPython 3.9 | abi3 | Linux glibc 2.17+ x86-64 | Details for lxephemeris-1.0.1-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl |
| lxephemeris-1.0.1-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl | CPython 3.9 | abi3 | Linux glibc 2.17+ ARM64 | Details for lxephemeris-1.0.1-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl |
| lxephemeris-1.0.1-cp39-abi3-macosx_11_0_arm64.whl | CPython 3.9 | abi3 | macOS 11.0+ ARM64 | Details for lxephemeris-1.0.1-cp39-abi3-macosx_11_0_arm64.whl |
| lxephemeris-1.0.1-cp39-abi3-macosx_10_12_x86_64.whl | CPython 3.9 | abi3 | macOS 10.12+ x86-64 | Details for lxephemeris-1.0.1-cp39-abi3-macosx_10_12_x86_64.whl |
Total release size: 8.3 MB
Release files / lxephemeris-1.0.1.tar.gz
| Download URL | lxephemeris-1.0.1.tar.gz |
|---|---|
| Size | 371.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6db92819811cee83b0b06a14fdbdd5e6b0c2cc722d0dfe5ef9675169cf4e4553
|
|
BLAKE2b-256 checksum How to use checksums |
0a5f902fb3c54787fa3e1e8702a4cc17967cd1a469808e8e920d76a3f6c75ec0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.16.0
|
Release files / lxephemeris-1.0.1-cp39-abi3-win_amd64.whl
| Download URL | lxephemeris-1.0.1-cp39-abi3-win_amd64.whl |
|---|---|
| Size | 1.5 MB |
| Tags | CPython 3.9 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
8c02edf50552309965474c4a0903db07927eeb00cbe4fbe3b23e2f600d75e12d
|
|
BLAKE2b-256 checksum How to use checksums |
3c8c343bceac02453c03a994c8d81f0eec14a448b077f51f98dc233b13e17935
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.16.0
|
Release files / lxephemeris-1.0.1-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
| Download URL | lxephemeris-1.0.1-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl |
|---|---|
| Size | 1.7 MB |
| Tags | CPython 3.9 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
6d38542c01b609c6db7fb4bd00e96d49fc463ee9ba55bc15e727297b07b4b87f
|
|
BLAKE2b-256 checksum How to use checksums |
c8d8f2193436d03a3a86f377fb89cb63dbccedc95d7d687a49ecc3a7cd1b1c12
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.16.0
|
Release files / lxephemeris-1.0.1-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
| Download URL | lxephemeris-1.0.1-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl |
|---|---|
| Size | 1.7 MB |
| Tags | CPython 3.9 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
a337d77efd0011e443b6c4c360d9580d2dd5f504b071486fc6182e2efca968f8
|
|
BLAKE2b-256 checksum How to use checksums |
3f255c28b5f6816c6cdf35cfee07266bc1b9570079b93d91f9e16749cc6f6817
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.16.0
|
Release files / lxephemeris-1.0.1-cp39-abi3-macosx_11_0_arm64.whl
| Download URL | lxephemeris-1.0.1-cp39-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 1.5 MB |
| Tags | CPython 3.9 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
4b5057f8d0bd6259fd0fcbba55bd20cbb67cbb1089b0129d611c18461cfe2d7b
|
|
BLAKE2b-256 checksum How to use checksums |
58e6cdf1d17646d640f596203c55d94cf005c1c1c651560e03e2d2a10c9006aa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.16.0
|
Release files / lxephemeris-1.0.1-cp39-abi3-macosx_10_12_x86_64.whl
| Download URL | lxephemeris-1.0.1-cp39-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 1.6 MB |
| Tags | CPython 3.9 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
598bb6bd6425f35bba98577f690794dde1bda1825868470cde63eaaa03c49e28
|
|
BLAKE2b-256 checksum How to use checksums |
43ad160abafa1dc2d361010c515ce5a373f9c4c9f512578336e1195f76a1b7dc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.16.0
|
Security for lxephemeris 1.0.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.