Astrometry.net: blind astrometric calibration for images nobody has catalogued
Astrometry.net -- automatic recognition of astronomical images
At a glance
- What is it?
- Astrometry.net solves a specific archival problem. Given an astronomical image with celestial coordinates you do not know or do not trust, it works out where the camera was pointing and returns standards-compliant astrometric metadata plus the catalogue of known objects in the field. The code is mostly C, the licence is GPL-3.0, and the public service sits at nova.astrometry.net.
- Who is it for?
- Adopt Astrometry.net when you hold a large collection of sky images whose coordinates are missing, wrong or unreliable, and you want plate solving plus catalogue cross-matching in one step rather than by hand. Do not adopt it if your pointing is already known precisely and you only need a catalogue lookup, because there are simpler tools for that.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem being solved: images whose pointing nobody recorded
Astrometry.net describes itself as automatic recognition of astronomical images, or standards-compliant astrometric metadata from data. The README states the use case without hedging: if you have astronomical imaging of the sky with celestial coordinates you do not know, or do not trust, then this is for you. Input an image and it gives back astrometric calibration metadata, plus lists of known objects falling inside the field of view.
That second half matters as much as the first. Plate solving is a well-understood problem and there are many implementations. What Astrometry.net adds is the archive-scale ambition behind it, stated in the README as the goal of creating correct, standards-compliant astrometric metadata for every useful astronomical image ever taken, past and future, in any state of archival disarray, with the hope of organising, annotating and making searchable the world's astronomical information.
That framing explains the architecture better than any feature list would. Blind astrometric calibration means the solver is given only the pixels and has to infer the pointing itself, without a catalogue of expected stars, without a known scale and without a hint about where on the sky the image was taken. The 2010 paper by Lang, Hogg, Mierle, Blanton and Roweis describes the method as blind astrometric calibration of arbitrary astronomical images, and the README asks academic users to cite it.
The service is public at nova.astrometry.net, the documentation is at astrometry.net/doc and on Read the Docs, and there is a Google Group forum for discussion. Code snapshots and releases are hosted at astrometry.net/downloads, and the code development happens on GitHub.
What the repository actually contains
The repository is a large, long-lived C project, and the top-level layout tells you how the pieces fit together.
There is an astrometry/ directory for the core, a solver/ directory, a net/ directory for the web service, a util/ directory, and a bin/ directory. There are vendored or adapted third-party components in their own directories: libkd/ for the kd-trees, gsl-an/ for an adapted GNU scientific library, and qfits-an/ for FITS file handling. There are also catalogs/, plot/, man/, doc/, demo/, docker/, etc/ and sdss/ directories, plus the standard build files, a configure script, a Makefile, a setup.py and an __init__.py at the root.
The Makefile spells out the dependency stack explicitly, and the ordering is the interesting part. It reads as a stack from the top down: solver/libastrometry.a is the astrometry.net core, then catalogs/libcatalogs.a, then util/libanfiles.a for astrometry.net index files and related data, then libkd/libkd.a for kd-trees, then util/libanutils.a for utilities, then either gsl-an/libgsl-an.a or the system GSL, the GNU scientific library, with wcslib marked optional, then qfits-an/libqfits.a for FITS files, and finally util/libanbase.a for basic stuff.
That is a genuine multi-language build in the old sense, with static libraries layered on top of each other. The comment also notes that the internal dependency stack is the reason makefile.common has to be copied rather than included, to avoid the implicit rules for that file being applied to itself.
The setup.py reflects the same structure from the Python side. It shells out to make for the version string, and its custom install command runs make -k, then make -k py, then make -k pyinstall and make -k install with the install directory and Python base directory passed through the environment. The custom build extension class does the same for build_ext. This is a Python wrapper around a C build, and the wrapper exists so that pip install does the right thing rather than requiring you to run the C build by hand first.
Running it: the Docker image and the index files
Docker containers are available, and the README's first example is a single solve:
docker run --volume "$(pwd):$(pwd)" -w "$(pwd)" astrometrynet/solver:0.98 solve-field image.jpgThe solve-field program is the workhorse. The volume mount and the working directory flag make the current directory visible inside the container so that the output files land where you expect.
The second example solves one of the example images shipped with the image, using an index file that comes with the Docker image:
(cd /tmp; docker run --volume "$(pwd):$(pwd)" -w "$(pwd)" astrometrynet/solver:0.98 solve-field --dir . /src/astrometry/demo/apod5.jpg)The README notes that the results files then appear in /tmp/apod5*.
The third example is the one that matters for real work, because the index files you need for your own targets are not shipped in the image. To use index files you have downloaded, you mount the directory containing them into the container at /usr/local/data:
(cd /tmp; docker run --volume "$(pwd):$(pwd)" --volume /data/index/4100:/usr/local/data -w "$(pwd)" astrometrynet/solver:0.98 solve-field --dir . /src/astrometry/demo/apod4.jpg)The index files are the reason this is a system rather than a program. Blind calibration works by matching the stars in your image against a set of index files built for particular scales and regions of the sky, and the ones for a given field are large. The image tag 0.98 in these examples is ahead of the most recent tagged release in the repository, which is 0.97 from 2024-12-02, so the container is tracking a different version line than the source tags.
The demo directory in the repository holds the same kind of material as a starting point: apod1.jpg through apod5.jpg with their .xyls companions, m44-1910-04-01.jpg and m44-1975-01-18.jpg, sdss.jpg with an sdss.xyls, an index file in demo/index-4119.fits and a Tycho-2 magnitude file in demo/tycho2-mag6.fits.
The licence: BSD-style code inside a GPL distribution
The licensing is the most consequential detail in the README, and it is stated in a way that requires reading carefully.
Parts of the code written by the Astrometry.net Team are licensed under a 3-clause BSD-style license, and the LICENSE file holds the full text. However, since this code uses libraries licensed under the GNU GPL, the whole work must be distributed under the GPL version 3 or later.
That is the standard relicensing situation: the team's own contributions are permissive, but the vendored or adapted libraries in the tree, the kd-trees, the adapted GSL and the adapted QFITS among them, carry copyleft terms that reach the whole. The badge in the README header points at the GPL version 3 licence page, and the Makefile header states the same thing in the source, noting that the suite is free software that you can redistribute and modify under the terms of the GNU General Public License version 2 or later, and that it is distributed in the hope that it will be useful but without any warranty.
For a scientific codebase used inside universities and observatories, a copyleft licence is a normal choice, and it means the derivation rules differ from the BSD impression the team licence creates. If you want to use the solver as a component inside a proprietary product, you need to read the licence text and the terms of the specific libraries you link, because the parts written by the team are not the constraint and the vendored parts are.
Copyright is held by the Astrometry.net Team, Michael Blanton, David W. Hogg, Dustin Lang, Keir Mierle and Sam Roweis, with 2006-2026 in the copyright line, and the README lists a further group of contributors including Sjoert van Velzen, Themos Tsikas, Andrew Hood, Thomas Stibor, Denis Vida, Ole Streicher, David Warde-Farley, Jon Barron, Christopher Stumm, Michal Kočer, Vladimir Kouprianov and others.
The build, the documentation and the release history
The build is a configure script plus a Makefile, with the Makefile taking an install directory argument, and the setup.py path for pip. The presence of util/makefile.common as the shared rules file means the top-level Makefile is mostly a thin layer, and the note about copying rather than including it shows how much of the build machinery predates modern conventions.
The documentation lives in two places. There is a doc/ directory in the repository and a Read the Docs site at astrometrynet.readthedocs.io, and the main site carries its own documentation at astrometry.net/doc. There is a man/ directory for manual pages, a plot/ directory for the plotting code, and an etc/ directory for the data that ships with the distribution, including the index files the solver needs.
The release history is short and slow. The three tagged releases are 0.97 from 2024-12-02, described as minor changes, 0.96 from 2024-09-14 described as support for numpy 2.0, and 0.95 from 2024-05-06 described as small fixes for Python 3.12 and better Dockerfiles. Each release note tells you exactly what kind of change it was, and two of the three are compatibility fixes, which is what a mature scientific tool needs.
The last push to the repository was on 2026-10-11, well after the 0.97 tag, so there is development beyond the newest release. That gap matters for the Docker image, which is at 0.98, and it means the source tree and the tagged release are not the same thing.
The build and test infrastructure is visible in the tree as a .travis.yml and a .circleci/ directory, which dates the CI configuration to the era when Travis was the default. The README also carries a notice that the project is not accepting LLM-generated pull requests at this time, which is a stated policy rather than an inference, and it is worth knowing before you plan to contribute.
Limits: the index files, the build, and what plate solving cannot fix
Several limits are visible in what the README describes.
The first is the index file dependency. Blind calibration needs a set of index files covering the scale and region of sky you are solving, and those files are large and are not shipped in the container, as the third Docker example makes plain. That means the container image is not self-sufficient for real work: you have to obtain the right index files, mount them at /usr/local/data, and keep them in step with the fields you work on. A workflow that runs on a random assortment of archive images needs an index collection covering all of them.
The second is the build. This is a C project with vendored static libraries and a Makefile whose rules live in util/makefile.common, plus a setup.py that shells out to make. That is not an obstacle on Linux, and the Docker image exists precisely so most users never meet it, but it does mean that installing on a platform without a straightforward toolchain, or working from the source rather than the container, is more involved than a pip install usually is.
The third is what the tool does not do. It solves pointing and cross-matches against a catalogue, and the README describes no photometric calibration, no image processing beyond what the solver needs, and no handling of the systematic errors that make old photographic plates hard. A field with a large colour index spread, or with a distorted lens, or with stars saturated on the emulsion, is the case where a solved position is least trustworthy.
The fourth is the version mismatch described above. The tags stop at 0.97, the container is at 0.98, and the branch has moved on since. Anyone who needs reproducible results should record the exact version they used rather than pulling the latest image.
Astrometry.net against a manual coordinate lookup and against a modern plate-solving tool
Two comparisons clarify where this fits.
The first is against looking the field up by hand, which is what people did before blind solving existed and what a lot of people still do for a handful of images. The difference in approach is scale and correctness. A human matches a few bright stars by eye, which works for a well-exposed wide field and fails for anything faint or badly distorted, and the result is a coordinate that is good to a few arcminutes and depends on the observer's care. A solver does the matching quantitatively against index files, and the result is a fitted WCS with residuals you can inspect.
The second is against a modern plate-solving package, of which there are several in the Python ecosystem, that ship a much smaller set of star indices and are aimed at a single exposure. The difference in approach is the index architecture. Astrometry.net's index files are hierarchical kd-trees, which is what the Makefile's dependency stack describes, and that structure is what allows it to search a large sky for the right match without loading the whole catalogue into memory. The smaller tools load a compact star list, which is faster for the field they were designed around and gives up the ability to solve an image of unknown scale in an arbitrary part of the sky.
So the choice is about the problem. If you have a targeted field, a modern plate solver with a bundled catalogue is less machinery. If you have an archive with unknown pointing, in any state of disarray, and you want the whole collection solved the same way with a traceable method, the Astrometry.net approach is the one built for it, and the twenty-year-old index files and the paper behind the method are part of why it is trusted.
The web service at nova.astrometry.net sits on top of the same machinery and is worth knowing about, since submitting an image to it is much less work than running the solver and managing index files yourself.
Editorial conclusion
Adopt Astrometry.net when you hold a large collection of sky images whose coordinates are missing, wrong or unreliable, and you want plate solving plus catalogue cross-matching in one step rather than by hand. Do not adopt it if your pointing is already known precisely and you only need a catalogue lookup, because there are simpler tools for that. Verify first that the index files for the sky scale and field centre you are solving are present, since the solver needs them, and check the licence position before you redistribute, because the project's own code is BSD-style while the libraries it links force the whole distribution to GPL-3.0.
Frequently asked questions
What does Astrometry.net do with an astronomical image?
It computes astrometric calibration metadata for images whose celestial coordinates you do not know or do not trust, by blind astrometric calibration, and returns the pointing together with lists of known objects falling inside the field of view. The README describes the aim as standards-compliant metadata for every useful astronomical image ever taken.
How do I run the Astrometry.net solver with Docker?
The README gives a one-liner that mounts your current directory and runs solve-field on an image using the astrometrynet/solver:0.98 image. To use index files you have downloaded yourself, mount the directory containing them into the container at /usr/local/data, for example with a second volume mapping /data/index/4100 to that path.
What licence applies to Astrometry.net?
Parts of the code written by the Astrometry.net Team are under a 3-clause BSD-style licence, but because the project uses libraries licensed under the GNU GPL, the whole work must be distributed under GPL version 3 or later. The Makefile header states the same terms in the source itself.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/dstndstn-astrometry-net)Was this useful?