@swisseph/browser
v1.1.0
Published
Swiss Ephemeris for browsers - WebAssembly astronomical calculations
Maintainers
Readme
@swisseph/browser
High precision astronomical calculations for browsers using WebAssembly.
Features
- ✅ Runs entirely in browser - No server required
- ✅ WebAssembly powered - Near-native performance
- ✅ Moshier ephemeris built-in - Works offline, ~250KB gzipped
- ✅ Optional Swiss Ephemeris - Load from CDN for JPL precision
- ✅ Modern TypeScript API - Same as @swisseph/node
- ✅ Type-safe - Enums, object returns, full TypeScript support
Installation
npm install @swisseph/browserQuick Start
Default: Moshier ephemeris (built-in, no setup)
import { SwissEphemeris, Planet, HouseSystem } from '@swisseph/browser';
// Initialize WASM module
const swe = new SwissEphemeris();
await swe.init();
// Calculate planetary position using Date object
const date = new Date('2007-03-03T00:00:00Z');
const jd = swe.dateToJulianDay(date);
const sun = swe.calculatePosition(jd, Planet.Sun);
console.log(`Sun: ${sun.longitude}°`);
// Calculate houses
const houses = swe.calculateHouses(jd, 40.7128, -74.0060, HouseSystem.Placidus);
console.log(`Ascendant: ${houses.ascendant}°`);
console.log(`MC: ${houses.mc}°`);Optional: Swiss Ephemeris files for maximum precision
const swe = new SwissEphemeris();
await swe.init();
// Load ephemeris files from CDN (~2MB, one-time download)
await swe.loadStandardEphemeris();
// Use Swiss Ephemeris for JPL precision
const sun = swe.calculatePosition(jd, Planet.Sun, CalculationFlag.SwissEphemeris);Core API
Initialization
const swe = new SwissEphemeris();
await swe.init();The WASM file is automatically loaded from the same directory as the JavaScript bundle. This works out-of-the-box with all modern bundlers (Vite, Webpack, Rollup, etc.).
Date & Time
// Convert JavaScript Date to Julian day (recommended)
swe.dateToJulianDay(date, calendarType?)
// Convert date components to Julian day
swe.julianDay(year, month, day, hour?, calendarType?)
// Convert Julian day back to date
swe.julianDayToDate(jd, calendarType?)Examples:
// Using Date object (easiest)
const jd = swe.dateToJulianDay(new Date('1990-05-15T14:30:00Z'));
// Using date components
const jd2 = swe.julianDay(1990, 5, 15, 14.5); // Same result
// Current time
const now = swe.dateToJulianDay(new Date());Planetary Positions
swe.calculatePosition(jd, body, flags?)
// Returns: { longitude, latitude, distance, longitudeSpeed, ... }Available bodies: Planet.Sun, Planet.Moon, Planet.Mercury, Planet.Venus, Planet.Mars, Planet.Jupiter, Planet.Saturn, Planet.Uranus, Planet.Neptune, Planet.Pluto
Houses
swe.calculateHouses(jd, latitude, longitude, houseSystem?)
// Returns: { cusps[], ascendant, mc, armc, vertex, ... }House systems: Placidus, Koch, Equal, WholeSign, Campanus, Regiomontanus, etc.
Eclipses
swe.findNextLunarEclipse(startJd, flags?, eclipseType?, backward?)
swe.findNextSolarEclipse(startJd, flags?, eclipseType?, backward?)
// Returns eclipse object with methods: isTotal(), isPartial(), getTotalityDuration(), etc.Utilities
swe.getCelestialBodyName(body) // Get name string
swe.version() // Swiss Ephemeris version
swe.close() // Free resources when doneEphemeris Options
Option 1: Moshier (Default - Built-in)
- No external files needed
- Small bundle size (~250KB gzipped)
- Sub-arcsecond accuracy
- Works offline immediately
- Major planets only (no asteroids)
Option 2: Swiss Ephemeris Files (Optional)
Load from jsDelivr CDN for maximum precision:
// Simple: Load standard files
await swe.loadStandardEphemeris();
// Or load from custom URLs
await swe.loadEphemerisFiles([
{ name: 'sepl_18.se1', url: 'https://your-cdn.com/sepl_18.se1' },
{ name: 'semo_18.se1', url: 'https://your-cdn.com/semo_18.se1' }
]);When to use Swiss Ephemeris files:
- Need JPL-level precision
- Professional astronomy applications
- Research requiring maximum accuracy
- Asteroid calculations
- ~2MB download acceptable
Note: Files are loaded into memory and persist only for the current session.
TypeScript Support
Full TypeScript types included. All enums and interfaces are exported:
import {
Planet, Asteroid, LunarPoint, // Celestial bodies
HouseSystem, // House systems
CalculationFlag, // Calculation options
CalendarType // Gregorian/Julian
} from '@swisseph/browser';Examples
Birth Chart Calculation
import {
SwissEphemeris,
Planet,
HouseSystem
} from '@swisseph/browser';
const swe = new SwissEphemeris();
await swe.init();
// Birth: May 15, 1990, 14:30 UTC, New York
const birthDate = new Date('1990-05-15T14:30:00Z');
const jd = swe.dateToJulianDay(birthDate);
// Calculate all planet positions
const planets = [
{ name: 'Sun', position: swe.calculatePosition(jd, Planet.Sun) },
{ name: 'Moon', position: swe.calculatePosition(jd, Planet.Moon) },
{ name: 'Mercury', position: swe.calculatePosition(jd, Planet.Mercury) },
{ name: 'Venus', position: swe.calculatePosition(jd, Planet.Venus) },
{ name: 'Mars', position: swe.calculatePosition(jd, Planet.Mars) },
{ name: 'Jupiter', position: swe.calculatePosition(jd, Planet.Jupiter) },
{ name: 'Saturn', position: swe.calculatePosition(jd, Planet.Saturn) },
{ name: 'Uranus', position: swe.calculatePosition(jd, Planet.Uranus) },
{ name: 'Neptune', position: swe.calculatePosition(jd, Planet.Neptune) },
{ name: 'Pluto', position: swe.calculatePosition(jd, Planet.Pluto) }
];
planets.forEach(({ name, position }) => {
console.log(`${name}: ${position.longitude.toFixed(4)}°`);
});
// Calculate houses
const houses = swe.calculateHouses(jd, 40.7128, -74.0060, HouseSystem.Placidus);
console.log(`Ascendant: ${houses.ascendant.toFixed(4)}°`);
console.log(`MC: ${houses.mc.toFixed(4)}°`);
for (let i = 1; i <= 12; i++) {
console.log(`House ${i}: ${houses.cusps[i].toFixed(4)}°`);
}
swe.close();Eclipse Search
import { SwissEphemeris } from '@swisseph/browser';
const swe = new SwissEphemeris();
await swe.init();
// Find next 5 lunar eclipses starting from Jan 1, 2025
let searchDate = swe.julianDay(2025, 1, 1);
for (let i = 0; i < 5; i++) {
const eclipse = swe.findNextLunarEclipse(searchDate);
const maxTime = swe.julianDayToDate(eclipse.maximum);
console.log(`\nEclipse ${i + 1}:`);
console.log(` Date: ${maxTime.toString()}`);
console.log(` Type: ${eclipse.isTotal() ? 'Total' : 'Partial'}`);
console.log(` Duration: ${eclipse.getTotalityDuration().toFixed(2)} hours`);
// Search for next eclipse after this one
searchDate = eclipse.maximum + 1;
}
swe.close();Planetary Aspects
import { SwissEphemeris, Planet } from '@swisseph/browser';
const swe = new SwissEphemeris();
await swe.init();
// Calculate for current time
const jd = swe.dateToJulianDay(new Date());
// Calculate positions
const sun = swe.calculatePosition(jd, Planet.Sun);
const moon = swe.calculatePosition(jd, Planet.Moon);
// Calculate aspect (angular difference)
let aspect = Math.abs(sun.longitude - moon.longitude);
if (aspect > 180) aspect = 360 - aspect;
console.log(`Sun-Moon aspect: ${aspect.toFixed(2)}°`);
// Classify aspect
if (Math.abs(aspect - 0) < 10) console.log('Conjunction');
else if (Math.abs(aspect - 60) < 10) console.log('Sextile');
else if (Math.abs(aspect - 90) < 10) console.log('Square');
else if (Math.abs(aspect - 120) < 10) console.log('Trine');
else if (Math.abs(aspect - 180) < 10) console.log('Opposition');
swe.close();Documentation
Complete documentation is available in the GitHub repository:
- Getting Started Guide - Installation and quick start
- API Reference - Complete browser API documentation
- Shared Types - TypeScript types and enums reference
- Usage Guides:
- Birth Charts - Calculate complete birth charts
- Eclipse Calculations - Find and analyze eclipses
- House Systems - Understanding house systems
- Julian Days - Working with Julian Day numbers
- Ephemeris Files - Understanding ephemeris files
Browser Compatibility
Requires WebAssembly support (all modern browsers):
- Chrome 90+
- Firefox 88+
- Safari 14+
- Edge 90+
Bundle Size
After gzip compression: ~200-250KB (WASM + TypeScript bundle)
Very reasonable for a high-precision astronomy library!
Comparison: Browser vs Node.js
| Feature | @swisseph/browser | @swisseph/node | |---------|-------------------|----------------| | Platform | Any browser | Node.js only | | Default Ephemeris | Moshier (built-in) | Swiss Ephemeris (bundled files) | | Optional Ephemeris | Swiss Ephemeris (CDN) | Moshier (built-in) | | Accuracy | Sub-arcsecond / JPL | JPL precision | | Asteroids | With Swiss Ephemeris files | Yes (bundled) | | Bundle Size | ~250KB (gzipped) | ~2MB + files | | Performance | Excellent | Excellent | | API | Identical | Identical |
Both packages share the same modern TypeScript API!
Development
Rebuilding the WASM Module
If you modify the C source code or need to update the WASM build (e.g., to export additional runtime methods), you'll need to rebuild:
Prerequisites:
- Emscripten SDK installed and activated
Steps:
# Install Emscripten (first time only)
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install latest
./emsdk activate latest
source ./emsdk_env.sh
# Rebuild WASM module
cd packages/browser
./build-wasm.sh
# Build TypeScript
npm run buildThe build script compiles the native Swiss Ephemeris C code to WebAssembly and exports:
- All calculation functions
- Runtime methods:
ccall,cwrap,FS(filesystem),allocateUTF8 - Virtual filesystem support for loading ephemeris files
License
AGPL-3.0 (same as Swiss Ephemeris)
Links
- GitHub Repository
- Swiss Ephemeris Documentation
- @swisseph/node - Native Node.js version
- @swisseph/core - Shared TypeScript types
