# Skyfield for planetary and satellite position calculations

> Skyfield is a pure-Python astronomy package for calculating planetary and Earth satellite positions. Its observation API combines named ephemeris bodies with timescales and returns right ascension, declination, and distance.

**skyfielders/python-skyfield** — Elegant astronomy for Python

- Repository: https://github.com/skyfielders/python-skyfield
- Stars: 1,791 · Forks: 268
- Language: Python
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/skyfielders-python-skyfield

## Skyfield's planetary and satellite calculation scope

Skyfield addresses a specific numerical astronomy task: calculating where one astronomical body appears from another at a specified time. The README describes the package as suitable for high precision research-grade positions of planets and Earth satellites. Its intended users include Python developers, educators, and science or research projects, based on the audience classifiers in `setup.py`.

The central abstraction is an observer and a target. A caller loads an ephemeris containing named bodies, selects `earth` and `mars`, creates a time from Skyfield's timescale, and then calls `earth.at(t).observe(mars)`. That returns an observation object from which the caller can request right ascension, declination, and distance through `radec()`. This API is useful when an application needs numerical coordinates rather than only a plotted chart.

Skyfield also contains examples concerning satellite downloads, comet charts, re-entry charts, observing charts, calendar generation, and daylight calculations. The repository layout therefore points toward several astronomy workflows, not just a single planet example. Still, the README does not define accuracy tolerances, supported coordinate transformations, or a guarantee for every satellite catalog. An adopter must match the selected data and calculation path to the required precision rather than relying on the package description alone.

## How Skyfield converts ephemeris data into observations

The first key data object in the README example is `de421.bsp`, loaded with `load('de421.bsp')`. It is accessed as a collection of bodies, which is why the same variable can yield both `earth` and `mars`. A second input is a timescale created by `load.timescale()`. The example uses `ts.now()` to place the calculation at the current time represented by that timescale.

The expression `earth.at(t).observe(mars)` defines the geometry in three stages. The `earth.at(t)` portion evaluates Earth's position at time `t`. Passing that position to `observe(mars)` creates an observer-to-target relationship. Calling `position.radec()` converts that observation into right ascension, declination, and distance. The README shows the returned values in these forms:

```text
10h 47m 56.24s
+09deg 03' 23.1"
2.33251 au
```

This structure keeps body selection, time selection, observation geometry, and result formatting as separate operations. It also gives applications a common path for other observation calculations. However, `ts.now()` is unsuitable for a value that must be reproduced later because the displayed numbers depend on when the program runs. The README does not provide a fixed-time example, so it also does not confirm the exact API for supplying a specific timestamp.

Skyfield describes itself as pure Python, but it is not dependency-free. `setup.py` requires `certifi`, `jplephem`, NumPy, and `sgp4`. The README singles out NumPy as the only binary dependency. That distinction matters when choosing an installation environment: the package itself consists of Python code, while its numerical and astronomy-related dependencies can still create platform and version constraints.

## Installing Skyfield and running the Mars observation example

The README says Skyfield can usually be installed once NumPy is available. It gives `pip` as the normal installation route. Install the package in the Python environment where the observation code will run:

```bash
pip install skyfield
```

A first calculation requires an ephemeris file. The README example uses `de421.bsp`, which is present at the repository's top level, but it does not show installation steps for copying or downloading data files. The following example is therefore the source-tree calculation documented in the README. Run it in an environment where `load('de421.bsp')` can locate that file.

```python
from skyfield.api import load

planets = load('de421.bsp')
earth, mars = planets['earth'], planets['mars']

ts = load.timescale()
t = ts.now()
position = earth.at(t).observe(mars)
ra, dec, distance = position.radec()

print(ra)
print(dec)
print(distance)
```

The program prints the three fields produced by `radec()`. The README presents them as hour-minute-second right ascension, degree-minute-second declination, and distance in astronomical units. Exact values change with time because the example calls `ts.now()`.

The repository also contains files such as `de405.bsp` and compressed catalog data under `skyfield/data`, based on the top-level and package layout. The README does not explain how `load()` resolves installed data files, nor does it associate each example with a preferred data file. Users of a packaged deployment should check the linked Skyfield installation documentation before assuming that an arbitrary ephemeris filename will resolve in the same way.

## Dependency and repository constraints for Skyfield adoption

The runtime metadata and repository development requirements describe different dependency sets. `setup.py` declares four install requirements: `certifi>=2017.4.17`, `jplephem>=2.13`, `numpy`, and `sgp4>=2.13`. The lower bounds permit later releases, but the repository does not provide a complete dependency compatibility matrix. It also leaves the runtime requirement on NumPy without an explicit version constraint.

`setup.py` classifies Python 2.7 and Python 3.7 through Python 3.13. The README also states that Skyfield is compatible with Python 2 and 3. Those sources establish the project's declared compatibility, but the README does not say that every dependency or example works with every listed interpreter. An engineer working in a constrained environment should resolve the declared requirements and check the linked installation documentation for that environment.

The repository's `requirements.txt` contains a separate group of development and documentation dependencies. It includes exact versions such as `astropy==5.1`, `numpy==1.18.5`, `matplotlib==3.3.0`, `pandas==1.3.5`, and `sphinx==1.7.2`. It also includes `https://github.com/brandon-rhodes/assay/archive/master.zip`. This file should not be treated as the normal production installation manifest because `setup.py`, rather than `requirements.txt`, defines `install_requires`.

The repository is not archived, and its last push was on 2026-09-29. Recent repository activity does not establish compatibility with a particular dependency update. There are also no GitHub releases, so the repository page does not provide release tags or a GitHub release history for selecting an upgrade target. The checkout does include `CHANGELOG.rst` and `RELEASE.md`, but their contents are not present in the README excerpt, so no specific upgrade or rollback procedure can be confirmed here.

## Skyfield data requirements and its lower-level library boundary

Skyfield is convenient when an application should work with named bodies, times, and observations rather than lower-level numerical primitives. A lower-level alternative is to work directly with the underlying astronomy libraries and ephemeris data. The runtime dependency on `jplehem>=2.13`, together with the presence of `de405.bsp` and `de421.bsp`, shows a path based on JPL ephemeris data without Skyfield's higher-level `load()`, `observe()`, and `radec()` interface.

The practical difference is the API layer. Skyfield handles the sequence used by the README example: load an ephemeris collection, select named bodies, obtain a time, observe one body from another, and request spherical coordinates. A direct implementation would need separate code for the lower-level operations. The README does not document those lower-level APIs, numerical conventions, or exception behavior, so this repository alone cannot establish which route will be faster or easier for a particular application.

This boundary also exposes a Skyfield limitation. Examples require data, not merely the installed Python package. The README uses `de421.bsp`, while the repository includes several astronomy files. It does not state the size, redistribution terms, or update policy for every data resource. Code that assumes `load('de421.bsp')` will always locate a suitable file can therefore fail outside the demonstrated setup.

Skyfield makes ephemeris and timescale choices visible, but the README does not provide a formal accuracy table or recommend a file for each use case. The phrase “high precision” should therefore be treated as a project claim, not as a quantified guarantee. The chosen ephemeris must be verified against the accuracy required by the application.

## MIT licensing and Skyfield upgrade responsibilities

`setup.py` identifies the package as licensed under `MIT`, and the repository includes a `LICENSE` file. Its classifiers include the OSI-approved MIT License identifier. This confirms the project's declared licensing model, although product-specific obligations still require review of the license text and dependency licenses. This article does not provide legal advice.

The dependency declarations create an operational upgrade issue. Installing Skyfield installs separate packages, and they are not vendored into the repository. A reproducible environment should record resolved dependency versions even though `setup.py` leaves `numpy` without a lower or upper bound. The minimum versions for `jplephem` and `sgp4` do not identify the newest releases checked with any particular Skyfield version.

Upgrade planning also lacks a GitHub release trail. The repository has no GitHub releases, so there is no release-page history for checking upgrade notes or selecting a tagged package through that channel. The repository does contain release-related files, but their contents are not documented in the README excerpt. Before changing a production dependency, an engineer should inspect `CHANGELOG.rst` and `RELEASE.md` in the intended checkout and compare their dependency declarations.

The linked examples also indicate that data and code evolve together. `examples/satellite_download.py` and the planetary examples rely on repository or documentation resources, while `skyfield/data` stores packaged data files. The repository layout does not say whether an example and its data are guaranteed to remain compatible across arbitrary checkouts. Pinning a Skyfield package and its resolved dependencies is therefore more defensible than installing an unrecorded package set for a calculation that must be reproduced.

## Conclusion

Skyfield fits Python developers and astronomy researchers who need a documented observation API for planetary or satellite positions. It is a poor fit if NumPy is unavailable or a non-Python library better matches existing numerical code. Before adoption, verify the required ephemeris data, expected accuracy, Python version compatibility, and dependency versions. The repository has no GitHub releases, and its last push was on 2026-09-29.

## FAQ

### How do I install Skyfield?

The README says to install it with `pip install skyfield` once NumPy is available. `setup.py` also declares `certifi`, `jplephem`, and `sgp4` as runtime dependencies.

### How do I calculate the position of Mars from Earth with Skyfield?

Load `de421.bsp`, select `earth` and `mars`, create a time from `load.timescale()`, and evaluate `earth.at(t).observe(mars)`. Call `position.radec()` to obtain right ascension, declination, and distance.

### What Python versions and binary dependencies does Skyfield declare?

The README calls Skyfield a pure-Python package compatible with Python 2 and 3 and identifies NumPy as its only binary dependency. `setup.py` classifies Python 2.7 and Python 3.7 through Python 3.13.

## Sources

- [Issues](https://github.com/skyfielders/python-skyfield/issues)
- [License: MIT](https://github.com/skyfielders/python-skyfield/blob/master/LICENSE)
- [README](https://github.com/skyfielders/python-skyfield/blob/master/README.md)
- [skyfielders/python-skyfield on GitHub](https://github.com/skyfielders/python-skyfield)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/skyfielders-python-skyfield
