npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@typescriptify/sweph

v1.0.2

Published

Swiss Ephemeris for TypeScript — high-precision astronomical calculations

Readme

@typescriptify/sweph

A pure TypeScript translation of the Swiss Ephemeris — the gold standard library for astronomical and astrological calculations.

This library lets you calculate the positions of the Sun, Moon, planets, and stars with high precision. You can compute house cusps, eclipses, rise/set times, and much more — all from TypeScript or JavaScript, with no native dependencies.

What can it do?

  • Planet positions — get the longitude, latitude, and distance of any planet at any date
  • House systems — calculate house cusps for 24+ house systems (Placidus, Koch, Whole Sign, etc.)
  • Fixed stars — positions and magnitudes of key stars (Spica, Regulus, Aldebaran, etc.)
  • Eclipses — find solar/lunar eclipses, occultations, compute eclipse paths
  • Rise/set times — sunrise, sunset, moonrise, planet transits
  • Ayanamsa — sidereal zodiac support with 40+ ayanamsa modes (Lahiri, True Citra, etc.)
  • Heliacal events — heliacal rising/setting of planets and stars
  • Orbital elements — Keplerian elements, nodes, apsides
  • Date conversions — Julian day, UTC, Delta T, sidereal time

Installation

npm install @typescriptify/sweph

Two API Styles

This library provides two ways to use it:

| | C-style API | Modern TypeScript API | |---|---|---| | Style | Direct translation of the C functions | Class-based wrapper with named return types | | State | Thread swed: SweData manually | Managed inside SwissEph instance | | Returns | Float64Array, positional indexing (xx[0]) | Named objects ({ longitude, latitude, ... }) | | Errors | Check return codes (ERR = -1) | Throws SwissEphError | | Time mode | Separate *Ut / *Et functions | Automatic routing via timeMode option | | Docs | This README (below) | src/SwissEph/ — see README and UseCases |

Modern API — if you want a clean, idiomatic TypeScript experience:

import { SwissEph } from '@typescriptify/sweph/SwissEph';
import { SE_SUN, SE_MARS } from '@typescriptify/sweph/constants';

const swe = new SwissEph();
const jd = SwissEph.julianDay(2025, 1, 1, 12);

const sun = swe.calc(jd, SE_SUN);
console.log(`Sun: ${sun.longitude.toFixed(4)}°, speed: ${sun.longitudeSpeed.toFixed(4)}°/day`);

swe.close();

See src/SwissEph/README.md for full documentation and src/SwissEph/UseCases/ for 27 detailed use case guides covering everything from planet positions to heliacal events.


C-style API — if you're familiar with the original Swiss Ephemeris C interface, the rest of this README is for you.

Quick Start

Every function takes a swed state object as its first argument. Create one at startup and reuse it:

import { createDefaultSweData } from '@typescriptify/sweph/types';
import { sweCalc } from '@typescriptify/sweph/sweph';
import { julDay } from '@typescriptify/sweph/swedate';
import {
  SE_SUN, SE_MOON, SE_MARS,
  SEFLG_MOSEPH, SEFLG_SPEED,
  SE_GREG_CAL,
} from '@typescriptify/sweph/constants';

// 1. Create the state object (do this once)
const swed = createDefaultSweData();

// 2. Convert a calendar date to a Julian day number
//    (January 1, 2025 at noon UT)
const jd = julDay(2025, 1, 1, 12.0, SE_GREG_CAL);

// 3. Calculate the Sun's position
const sun = sweCalc(swed, jd, SE_SUN, SEFLG_MOSEPH | SEFLG_SPEED);

console.log(`Sun longitude: ${sun.xx[0].toFixed(4)}°`);  // ecliptic longitude
console.log(`Sun latitude:  ${sun.xx[1].toFixed(4)}°`);  // ecliptic latitude
console.log(`Sun distance:  ${sun.xx[2].toFixed(6)} AU`); // distance in AU
console.log(`Sun speed:     ${sun.xx[3].toFixed(4)}°/day`); // daily motion

The result xx is a Float64Array with 6 elements: [longitude, latitude, distance, lonSpeed, latSpeed, distSpeed].

Calculating the Moon

const moon = sweCalc(swed, jd, SE_MOON, SEFLG_MOSEPH | SEFLG_SPEED);
console.log(`Moon: ${moon.xx[0].toFixed(4)}° at ${moon.xx[3].toFixed(2)}°/day`);

Calculating houses

import { sweHouses } from '@typescriptify/sweph/swehouse';

const cusps = new Array(37).fill(0);  // cusp[1]..cusp[12]
const ascmc = new Array(10).fill(0);  // ascmc[0]=AC, ascmc[1]=MC, ascmc[2]=ARMC, etc.

// Placidus houses for London at the given time
sweHouses(swed, jd, 51.5074, -0.1276, 'P', cusps, ascmc);

console.log(`Ascendant: ${ascmc[0].toFixed(2)}°`);
console.log(`Midheaven: ${ascmc[1].toFixed(2)}°`);
for (let i = 1; i <= 12; i++) {
  console.log(`  House ${i}: ${cusps[i].toFixed(2)}°`);
}

House system codes: 'P' = Placidus, 'K' = Koch, 'E' = Equal, 'W' = Whole Sign, 'C' = Campanus, 'R' = Regiomontanus, 'B' = Alcabitius, and many more.

Ephemeris Modes

This library supports three levels of precision:

| Mode | Flag | Precision | Data files needed? | |---|---|---|---| | Moshier | SEFLG_MOSEPH | ~1 arcsecond | No (built-in) | | Swiss Ephemeris | SEFLG_SWIEPH | ~0.001 arcsecond | Yes (.se1 files) | | JPL | SEFLG_JPLEPH | ~0.001 arcsecond | Yes (JPL DE file) |

Moshier mode works out of the box with no data files. It uses built-in analytical models and is accurate enough for most purposes.

Swiss Ephemeris mode reads pre-computed binary data files (.se1) for higher precision. See Loading Ephemeris Data Files below.

JPL mode reads NASA JPL Development Ephemeris binary files (e.g., de441.eph). See Loading JPL Files below.

Loading Ephemeris Data Files

Where to download

Download .se1 files from the official Swiss Ephemeris site:

  • https://www.astro.com/ftp/swisseph/ephe/

The most common files you'll need:

  • sepl_18.se1 — planet data (1800 AD - 2400 AD)
  • semo_18.se1 — Moon data (1800 AD - 2400 AD)

For other date ranges, download the corresponding files (e.g., sepl_06.se1 for 600 AD - 1200 AD).

How to load them

Since this is a pure TypeScript library (no filesystem access), you load files as ArrayBuffers. How you get the ArrayBuffer depends on your environment:

Node.js:

import { readFileSync } from 'fs';
import { sweSetEphemerisFile, sweCalc } from '@typescriptify/sweph/sweph';
import { createDefaultSweData } from '@typescriptify/sweph/types';
import { SE_SUN, SEFLG_SWIEPH, SEFLG_SPEED } from '@typescriptify/sweph/constants';

const swed = createDefaultSweData();

// Load the planet and moon ephemeris files
const seplBuf = readFileSync('./ephe/sepl_18.se1');
const semoBuf = readFileSync('./ephe/semo_18.se1');

sweSetEphemerisFile('sepl_18.se1', seplBuf.buffer, swed);
sweSetEphemerisFile('semo_18.se1', semoBuf.buffer, swed);

// Now you can use SEFLG_SWIEPH for higher precision
const sun = sweCalc(swed, 2451545.0, SE_SUN, SEFLG_SWIEPH | SEFLG_SPEED);
console.log(`Sun (SWIEPH): ${sun.xx[0].toFixed(6)}°`);

Browser (fetch):

const response = await fetch('/ephe/sepl_18.se1');
const buffer = await response.arrayBuffer();
sweSetEphemerisFile('sepl_18.se1', buffer, swed);

React Native (expo-file-system, react-native-fs, etc.):

// Read the file into an ArrayBuffer using your preferred file library,
// then pass it to sweSetEphemerisFile() the same way.

Loading JPL files

For the highest precision using NASA JPL ephemerides:

import { sweLoadJplFile, sweCalc } from '@typescriptify/sweph/sweph';
import { SEFLG_JPLEPH, SEFLG_SPEED, SE_MARS } from '@typescriptify/sweph/constants';

// Download a JPL DE file (e.g., de441.eph) from:
// https://ssd.jpl.nasa.gov/ftp/eph/planets/Linux/
const jplBuffer = readFileSync('./ephe/de441.eph');

const result = sweLoadJplFile(swed, jplBuffer.buffer, 'de441.eph');
if (result.retc < 0) {
  console.error('Failed to load JPL file:', result.serr);
}

// Now use SEFLG_JPLEPH
const mars = sweCalc(swed, 2451545.0, SE_MARS, SEFLG_JPLEPH | SEFLG_SPEED);

More Examples

Sidereal zodiac (ayanamsa)

import { sweSetSidMode, sweGetAyanamsa } from '@typescriptify/sweph/sweph';
import { SE_SIDM_LAHIRI } from '@typescriptify/sweph/constants';

sweSetSidMode(swed, SE_SIDM_LAHIRI, 0, 0);
const ayanamsa = sweGetAyanamsa(swed, jd);
console.log(`Lahiri ayanamsa: ${ayanamsa.toFixed(4)}°`);

// To get sidereal positions, add SEFLG_SIDEREAL to your flags:
import { SEFLG_SIDEREAL } from '@typescriptify/sweph/constants';
const sunSid = sweCalc(swed, jd, SE_SUN, SEFLG_MOSEPH | SEFLG_SIDEREAL);
console.log(`Sun (sidereal): ${sunSid.xx[0].toFixed(4)}°`);

Fixed stars

import { sweFixstar } from '@typescriptify/sweph/sweph';

const spica = sweFixstar(swed, 'Spica', jd, SEFLG_MOSEPH);
console.log(`Spica: ${spica.xx[0].toFixed(4)}°`);

Sunrise and sunset

import { sweRiseTrans } from '@typescriptify/sweph/swecl';
import { SE_CALC_RISE, SE_CALC_SET } from '@typescriptify/sweph/constants';
import { revJul } from '@typescriptify/sweph/swedate';

const geopos = [-0.1276, 51.5074, 0]; // [longitude, latitude, altitude_meters]

const rise = sweRiseTrans(
  swed, jd, SE_SUN, null, SEFLG_MOSEPH,
  SE_CALC_RISE, geopos, 1013.25, 10, null
);

if (rise.retval >= 0) {
  const d = revJul(rise.tret, SE_GREG_CAL);
  console.log(`Sunrise: ${d.year}-${d.month}-${d.day} ${d.hour.toFixed(2)} UT`);
}

Solar eclipse search

import { sweSolEclipseWhenGlob, sweSolEclipseWhere } from '@typescriptify/sweph/swecl';

// Find the next solar eclipse after January 1, 2025
const startJd = julDay(2025, 1, 1, 0, SE_GREG_CAL);
const ecl = sweSolEclipseWhenGlob(swed, startJd, SEFLG_MOSEPH, 0, 0);

if (ecl.retval > 0) {
  const d = revJul(ecl.tret[0], SE_GREG_CAL);
  console.log(`Eclipse maximum: ${d.year}-${d.month}-${d.day} ${d.hour.toFixed(2)} UT`);

  const where = sweSolEclipseWhere(swed, ecl.tret[0], SEFLG_MOSEPH);
  console.log(`Central path: lon=${where.geopos[0].toFixed(1)}° lat=${where.geopos[1].toFixed(1)}°`);
}

Azimuth and altitude

import { sweAzalt } from '@typescriptify/sweph/swecl';
import { SE_ECL2HOR } from '@typescriptify/sweph/constants';

const xaz = [0, 0, 0]; // [azimuth, trueAltitude, apparentAltitude]
sweAzalt(
  swed, jd, SE_ECL2HOR,
  [-0.1276, 51.5074, 0],  // geopos
  1013.25, 10,              // pressure (mbar), temperature (C)
  [sun.xx[0], sun.xx[1], sun.xx[2]], // ecliptic lon, lat, distance
  xaz
);
console.log(`Sun azimuth: ${xaz[0].toFixed(2)}°, altitude: ${xaz[2].toFixed(2)}°`);

Orbital elements

import { sweGetOrbitalElements } from '@typescriptify/sweph/swecl';

const orb = sweGetOrbitalElements(swed, jd, SE_MARS, SEFLG_MOSEPH);
console.log(`Mars semi-major axis: ${orb.dret[0].toFixed(4)} AU`);
console.log(`Mars eccentricity:    ${orb.dret[1].toFixed(4)}`);
console.log(`Mars inclination:     ${orb.dret[2].toFixed(2)}°`);

Planetary nodes and apsides

import { sweNodAps } from '@typescriptify/sweph/swecl';

const nod = sweNodAps(swed, jd, SE_MARS, SEFLG_MOSEPH, 0);
console.log(`Mars ascending node:  ${nod.xnasc[0].toFixed(4)}°`);
console.log(`Mars descending node: ${nod.xndsc[0].toFixed(4)}°`);
console.log(`Mars perihelion:      ${nod.xperi[0].toFixed(4)}°`);
console.log(`Mars aphelion:        ${nod.xaphe[0].toFixed(4)}°`);

Heliacal rising

import { sweHeliacalUt } from '@typescriptify/sweph/swehel';

const hel = sweHeliacalUt(
  swed, jd,
  [-0.1276, 51.5074, 0],          // geopos
  [1013.25, 10, 50, 0.25, 0, 0],  // atmospheric conditions
  [0, 0, 0, 0, 0, 0],             // observer conditions
  'Venus', 1, SEFLG_MOSEPH
);
if (hel.retval >= 0) {
  const d = revJul(hel.dret[0], SE_GREG_CAL);
  console.log(`Venus heliacal rising: ${d.year}-${d.month}-${d.day}`);
}

Topocentric positions

import { sweSetTopo } from '@typescriptify/sweph/sweph';
import { SEFLG_TOPOCTR } from '@typescriptify/sweph/constants';

// Set observer location: London
sweSetTopo(swed, -0.1276, 51.5074, 0);

const moonTopo = sweCalc(swed, jd, SE_MOON, SEFLG_MOSEPH | SEFLG_TOPOCTR | SEFLG_SPEED);
console.log(`Moon (topocentric): ${moonTopo.xx[0].toFixed(4)}°`);

Cleanup

When you're done, free resources:

import { sweClose } from '@typescriptify/sweph/sweph';
sweClose(swed);

House Systems

| Code | Name | |---|---| | P | Placidus | | K | Koch | | O | Porphyrius | | R | Regiomontanus | | C | Campanus | | E | Equal (from Ascendant) | | W | Whole Sign | | B | Alcabitius | | M | Morinus | | X | Axial Rotation (Meridian) | | H | Azimuthal (Horizontal) | | T | Polich/Page (Topocentric) | | G | Gauquelin sectors (36 cusps) | | A | Equal (from Aries 0) | | D | Equal (MC) | | F | Carter (Poli-Equatorial) | | I | Sunshine / Makransky | | J | Sunshine / Treindl | | L | Pullen SD (sinusoidal delta) | | N | Pullen SR (sinusoidal ratio) | | Q | Pullen cumulative | | S | Sripati | | U | Krusinski-Pisa-Goelzer | | V | Vehlow Equal | | Y | APC houses |

Planet Constants

| Constant | Planet | |---|---| | SE_SUN | Sun | | SE_MOON | Moon | | SE_MERCURY | Mercury | | SE_VENUS | Venus | | SE_MARS | Mars | | SE_JUPITER | Jupiter | | SE_SATURN | Saturn | | SE_URANUS | Uranus | | SE_NEPTUNE | Neptune | | SE_PLUTO | Pluto | | SE_MEAN_NODE | Mean Lunar Node | | SE_TRUE_NODE | True Lunar Node | | SE_MEAN_APOG | Mean Lunar Apogee (Black Moon Lilith) | | SE_OSCU_APOG | Osculating Lunar Apogee | | SE_CHIRON | Chiron | | SE_EARTH | Earth |

About This Project

This is a line-by-line TypeScript translation of the Swiss Ephemeris C library (~30,000 lines of C translated to ~15 TypeScript source files). All 9 C source files have been translated, covering all 106 public API functions.

Key design decisions:

  • No global state — all functions take an explicit swed: SweData parameter
  • No filesystem access — ephemeris files are loaded as ArrayBuffers, making the library work in any JavaScript environment (Node.js, browsers, React Native, etc.)
  • No native dependencies — pure TypeScript, no WASM, no C bindings

This is a TypeScript translation based on the Node.js wrapper sweph by Timotej Valentin Rojko. The underlying Swiss Ephemeris is by Astrodienst AG.

License

This project is a TypeScript translation and is bound by the license of the original Swiss Ephemeris:

  • AGPL-3.0 for open-source use
  • LGPL-3.0 for holders of a professional Swiss Ephemeris license from Astrodienst AG

See the original repository for full license details: https://github.com/timotejroiko/sweph

The Swiss Ephemeris itself is Copyright (C) 1997-2021 Astrodienst AG, Switzerland.