API · v1

Die SkySolver-API

Löse ein Foto des Nachthimmels oder eine Liste seiner Sterne per Plate Solving und zeichne seine Beschriftung, als SVG zum Darüberlegen oder als JSON zum Selberzeichnen; oder löse ein Foto des Mondes: dieselben Solver und dieselben Beschriftungen wie in der Werkstatt. Die API ist kostenlos und braucht keinen Schlüssel, und Programme für den Online-Solver von Astrometry.net, etwa N.I.N.A. und KStars, können sie nutzen, wenn du eine einzige Adresse änderst: so geht’s.

Überblick

Kein Schlüssel
Kostenlos und anonym: kein Konto, kein API-Schlüssel.
Ratenbegrenzt
Je Client-Adresse, danach, wie schwer der Endpunkt ist.
Nichts wird behalten
Bilder, Sternlisten und Ergebnisse werden weder gespeichert noch protokolliert.
  • Basis-URL https://skysolver.app/api/v1. Anfragen und Antworten sind JSON (UTF-8); die Beschriftung kann auch als SVG kommen.
  • Vier Endpunkte: ein Bild lösen, als Base64 gesendet, Sternpositionen lösen, die du selbst gemessen hast, ein Mondfoto lösen und ein gelöstes Bild beschriften.
  • CORS ist offen: Du kannst die API aus einer Webseite heraus aufrufen.
  • Versionen: Inkompatible Änderungen bekommen einen neuen Pfad (/api/v2); v1 gewinnt nur optionale Felder hinzu. Das OpenAPI-Dokument beschreibt jedes Modell.
  • Faire Nutzung: Der Dienst ist kostenlos und läuft auf einem kleinen Server. Für große Stapel löse Sternlisten, die du selbst erkennst, oder frag unter [email protected].

Schnellstart

Ein Foto lösen, dann seine Beschriftung als SVG in der Größe des Fotos holen, zum Darüberlegen:

shell
# 1. solve: the body is {"image": "<the file in base64>"}
base64 < photo.jpg | jq -Rs '{image: .}' \
  | curl -s https://skysolver.app/api/v1/solve/image \
      -H 'Content-Type: application/json' --data-binary @- > solution.json

# 2. annotate: the whole solution goes in as the sky model
jq '{solution: ., format: "svg"}' solution.json \
  | curl -s https://skysolver.app/api/v1/annotate \
      -H 'Content-Type: application/json' --data-binary @- > annotation.svg

Dasselbe in JavaScript (Node 18 oder neuer; im Browser unterscheidet sich nur das Lesen der Datei):

javascript
import { readFile } from "node:fs/promises";

const post = (path, body) => fetch("https://skysolver.app/api/v1" + path, {
  method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body),
});

// in a browser: FileReader's readAsDataURL(file) gives a data: URL, which works as it is
const image = (await readFile("photo.jpg")).toString("base64");
const solution = await (await post("/solve/image", { image })).json();
if (solution.solved) {
  const answer = await post("/annotate", { solution, time: "2024-10-12T21:34:05+02:00" });
  const svg = await answer.text();
}

Und in Python:

python
import base64, json, urllib.request

API = "https://skysolver.app/api/v1"

def post(path, body):
    req = urllib.request.Request(API + path, data=json.dumps(body).encode(),
                                 headers={"Content-Type": "application/json"})
    with urllib.request.urlopen(req) as r:
        return r.read()

with open("photo.jpg", "rb") as f:
    image = base64.b64encode(f.read()).decode()
solution = json.loads(post("/solve/image", {"image": image}))
if solution["solved"]:
    print(solution["center"], solution["scale_arcsec"])
    svg = post("/annotate", {"solution": solution, "format": "svg"})

Grenzen

Jede Client-Adresse hat je Endpunkt einen Eimer von Anfragen: bis zu burst auf einmal, mit gleichmäßiger Rate wieder aufgefüllt. Eine Anfrage darüber hinaus wird sofort mit 429 und Retry-After beantwortet. Jede Antwort trägt RateLimit-Limit (den Burst), RateLimit-Remaining, RateLimit-Reset (Sekunden, bis der Eimer voll ist) und RateLimit-Policy.

EndpunktBurstAuffüllenAnfragekörper
POST /solve/image101 pro Minute28 MB (eine 20-MB-Datei in Base64)
POST /solve/stars3030 pro Minute4 MB
POST /solve/moon2010 pro Minute28 MB (eine 20-MB-Datei in Base64)
POST /annotate3030 pro Minute2 MB
GET /health6060 pro Minute–
  • Bilder: höchstens 20 MB und 120 Megapixel. Der Solver sucht höchstens time_limit_ms lang (1–30 s, standardmäßig 12 s). Ein Mondfoto wird mit bis zu 2048 Pixeln auf der längeren Seite gelöst (größere werden vorher verkleinert; die Antwort ist in den Pixeln der Datei) und braucht höchstens ein paar Sekunden.
  • Sternlisten: 5 bis 10.000 Sterne; die 3.000 hellsten werden verwendet.
  • Ausgelastet: Der Server rechnet ein paar Lösungen gleichzeitig (max_concurrent in health). Darüber hinaus wird eine Anfrage sofort mit 429, error: "busy" und Retry-After beantwortet: Warte so lange, plus eine zufällige Sekunde oder so, und schick sie noch einmal.
  • GET /health liefert die geltenden Grenzen.

Konventionen

  • Himmelskoordinaten sind Grad im ICRS (J2000): RA 0–360, Dec −90–90.
  • Pixel zählen ab 0 in der Mitte des Pixels oben links; x wächst nach rechts und y nach unten. Die linke obere Ecke des Bildes ist daher (−0,5, −0,5) und seine Mitte (width/2 − 0,5, height/2 − 0,5). FITS zählt ab 1: Sternlisten können das angeben (pixel_origin), und fits_header verwendet die FITS-eigene Konvention.
  • Zeiten sind ISO 8601 mit UTC-Offset oder Z: 2024-10-12T21:34:05+02:00. Eine Zeit ohne wird abgelehnt, nie geraten.
  • Fehler sind {"error": code, "message": text}, mit details für ungültige Felder: siehe Fehler.

Ein Bild lösen

POST/api/v1/solve/image10 auf einmal · 1 pro Minute

Erkennt die Sterne eines Bildes und findet, wohin am Himmel es zeigt: blind, ohne Hinweis auf Position, Maßstab oder Drehung, für Bildfelder von ein paar Bogenminuten bis zu Ganzhimmel-Panoramen. Das Bild wird im Arbeitsspeicher dekodiert und gelöst und nicht behalten.

Parameter
image
stringerforderlich
Die Bilddatei, Base64-kodiert (Standard- oder URL-sicheres Alphabet; ein Präfix data:image/…;base64, ist in Ordnung). Höchstens 20 MB dekodiert und 120 Megapixel. Formate: JPEG, PNG (8/16 Bit), TIFF (8/16/32 Bit und Float; unkomprimiert, LZW, ZIP, PackBits), FITS (Integer oder Float; Grau, RGB oder das rohe Bayer-Mosaik einer Farbkamera), XISF (unkomprimiert oder zlib), BMP, GIF, TGA und PSD. Lineare Daten (Stacks, FITS, XISF) werden vor der Erkennung gestreckt.
time_limit_ms
integeroptional
Wie lange der Solver suchen darf, bevor er aufgibt.
Standard 12000Erlaubt 1000–30000
Anfrage
{
  "image": "/9j/4AAQSkZJRgABAQEASABIAAD…",
  "time_limit_ms": 12000
}

Die Antwort ist die Lösung, plus image (format, width, height) und capture: wann und wo das Foto aufgenommen wurde, laut seinen Metadaten (EXIF, XMP, IPTC, FITS-Header, XISF-Eigenschaften).

capture
time
object | null
Die Aufnahmezeit, oder null, wenn die Datei keine hat.
└utc
string | null
Der Zeitpunkt in UTC: null, wenn die Datei eine Uhrzeit ohne Zeitzone angibt (EXIF vor 2.31, Lightrooms XMP).
└local
string
Die Uhrzeit, wie geschrieben: die Ortszeit der Kamera bei EXIF, UTC bei FITS.
└utc_offset
string | null
Der Offset der Uhr, +02:00; null, wenn unbekannt.
└source
string
Wo sie gelesen wurde: EXIF DateTimeOriginal, FITS DATE-OBS, XISF Observation:Time:Start…
└exposure_s
number
Die Belichtung (oder bei einem Stack vom ersten Beginn bis zum letzten Ende), wenn bekannt; die Zeit ist dann ihre Mitte.
└note
string
Etwas zum Prüfen: ein Stack, dessen Zeit die eines seiner Einzelbilder ist, eine Kamera, bei der vielleicht keine Zone gesetzt war.
└date_only
boolean
true, wenn die Datei ein Datum ohne Uhrzeit angibt.
location
object | null
Wo es aufgenommen wurde, aus dem GPS oder den FITS-Keywords des Standorts: {lat, lon, height, source}, Grad östlich und nördlich, Meter.
other_dates
array
Weitere Daten in der Datei, die nicht die Aufnahmezeit sein müssen (Erstellung, Änderung), geformt wie time.
Antwort (gekürzt)
{
  "api_version": "1.0",
  "solved": true,
  "width": 2048,
  "height": 1366,
  "wcs": {
    "ctype": "RA---TAN-SIP",
    "crval": [57.56884791, 30.441625],
    "crpix": [1023.5, 682.5],
    "cd": [[0.0004834903827, 0.008644326623], [-0.008637593318, 0.0004834749004]],
    "sip": { "order": 3, "a": [[0, 2, -1.585329748e-7], …], "b": […], "inv_order": 4, "ap": […], "bp": […] }
  },
  "projection": null,
  "center": { "ra": 57.56884791, "dec": 30.441625 },
  "corners": [{ "name": "top-left", "x": -0.5, "y": -0.5, "ra": 49.44900035, "dec": 38.65911116 }, …],
  "fov": { "width_deg": 17.6401047, "height_deg": 11.79908067 },
  "scale_arcsec": 31.15610913,
  "rotation_deg": 266.7987974,
  "parity": "normal",
  "stats": { "stars": 3294, "matches": 972, "rms_px": 0.3723350842, "log_odds": 3198.350966, … },
  "fits_header": "SIMPLE  =                    T …",
  "matched": [[1988.17, 1290.68, 63.70586, 22.302973, 8.59], …],
  "timing_ms": { "solve": 153.9, "detect": 40.3, "decode": 507.7, "server": 844.4 },
  "image": { "format": "FITS", "width": 2048, "height": 1366 },
  "capture": {
    "time": { "utc": "2025-08-16T21:00:00.000Z", "local": "2025-08-16T23:00:00.000", "utc_offset": "+02:00",
              "source": "FITS DATE-OBS", "exposure_s": 60 },
    "location": { "lat": 52.2297, "lon": 21.0122, "height": 110, "source": "FITS SITELAT/SITELONG" },
    "other_dates": []
  }
}

Sternpositionen lösen

POST/api/v1/solve/stars30 auf einmal · 30 pro Minute

Löst aus Sternpositionen, die du selbst gemessen hast (SExtractor, SEP, photutils, PixInsights StarDetector, deine eigenen Zentroide): Das Bild verlässt deinen Rechner nie, und die Anfrage ist ein paar Kilobyte groß. So löst die Werkstatt.

Parameter
width
integererforderlich
Bildbreite in Pixeln.
Erlaubt 8–100000
height
integererforderlich
Bildhöhe in Pixeln.
Erlaubt 8–100000
stars
arrayerforderlich
Sternpositionen, jede als [x, y], [x, y, flux] oder {"x": …, "y": …, "flux": …}. flux ist ein beliebiges positives Helligkeitsmaß (Summe, Spitze, …): Gib es für jeden Stern an oder für keinen, und ohne es liste die Sterne die hellsten zuerst. 30 bis 300 Sterne sind reichlich; die 3.000 hellsten werden verwendet. Die Positionen müssen im Bild liegen.
Erlaubt 5–10000 items
pixel_origin
integeroptional
0: Die Mitte des ersten Pixels ist (0, 0), wie in numpy und OpenCV. 1: Sie ist (1, 1), wie in FITS, SExtractor, astrometry.net und DS9. Antworten sind immer 0-basiert.
Standard 0Erlaubt 0 · 1
time_limit_ms
integeroptional
Wie lange der Solver suchen darf.
Standard 12000Erlaubt 1000–30000
Anfrage
{
  "width": 6000,
  "height": 4000,
  "stars": [
    [3735.37, 69.14, 51230],
    [2120.04, 1987.51, 48810],
    { "x": 812.6, "y": 3020.9, "flux": 47002 },
    …
  ]
}

Die Antwort ist die Lösung.

Die Lösung

Beide Sternfeld-Endpunkte antworten mit diesem Objekt.

Felder
solved
boolean
Ob eine Lösung gefunden wurde. Ein Foto, das sich nicht lösen lässt, ist trotzdem eine 200-Antwort, mit solved: false und einem error.
width, height
integer
Die Bildgröße in Pixeln.
center
object | null
Der Himmel in der Mitte des Bildes: {ra, dec} in Grad. null, wenn die Mitte eines Ganzhimmelbildes nicht am Himmel liegt.
corners
array
Die vier äußeren Ecken des Bildes, top-left, top-right, bottom-right, bottom-left: jede {name, x, y, ra, dec}, mit ra und dec null, wo eine Ecke nicht am Himmel liegt.
fov
object
{width_deg, height_deg}: die Winkellänge der horizontalen und vertikalen Mittellinie des Bildes.
scale_arcsec
number
Bogensekunden pro Pixel in der Mitte.
rotation_deg
number
Wohin das Oben des Bildes zeigt: Grad von Norden über Osten (0: Norden ist oben, 90: Osten ist oben).
parity
string
Gespiegelte Bilder (in der Bearbeitung gespiegelt oder durch einen Zenitspiegel) werden auch gelöst.
Erlaubt normal · mirrored
wcs
object | null
Die Lösung als TAN oder TAN-SIP: crval (RA, Dec des Referenzpixels), crpix (das Referenzpixel, 0-basiert), cd (Grad pro Pixel) und sip (Verzeichnungspolynome, Terme [p, q, coefficient]). null bei Projektionslösungen.
projection
object | null
Die Lösung als Projektionsmodell, für Panoramen, Fisheye- und Ganzhimmelansichten, die kein TAN-SIP erfasst; sonst null. Übergib es, oder die ganze Lösung, an /annotate.
stats
object
stars (erkannt oder übergeben), matches, rms_px (wie weit die zugeordneten Sterne vom Modell abweichen), log_odds (die Evidenz für die Zuordnung, ein natürlicher Logarithmus: Eine Lösung braucht 25 und 10 zugeordnete Sterne) und Details der Suche.
fits_header
string | null
Die TAN-SIP-Lösung als FITS-WCS-Header (80-Zeichen-Karten; FITS' 1-basiertes CRPIX), bereit zum Einfügen in eine FITS-Datei. null bei Projektionslösungen.
matched
array
Die Katalogsterne (Gaia DR3), die die Lösung zugeordnet hat, bis zu ein paar tausend: je [x, y, ra, dec, magnitude], die Helligkeit Gaias G.
timing_ms
object
decode (Lesen der Datei), detect, solve und die Gesamtzeit des servers für die Anfrage, in Millisekunden.
error
string
Warum es keine Lösung gibt (wenn solved false ist).
api_version
string
1.0

Ein Mondfoto lösen

POST/api/v1/solve/moon20 auf einmal · 10 pro Minute

Findet den Mond in einem Foto und passt seine Scheibe an: blind, bei jedem Maßstab, jeder Drehung und Spiegelung, in jeder Phase, ob das Bild die ganze Scheibe, einen Teil davon oder eine Nahaufnahme weniger Krater zeigt. Das bandpassgefilterte Foto wird an jeder Position, Drehung und Parität als Mischung aus drei festen Karten der Vorderseite (der Albedo und ihrer zwei Steigungen) abgeglichen, denn das macht jede Sonnenrichtung aus dem Boden; der Anteil des Fotos, den die Mischung erklärt, ist das Vertrauen, und der Mondrand, wenn es einen gibt, legt die Libration fest. Die Antwort platziert jeden Punkt des Fotos auf dem Mond: Mitte, Radius und Ausrichtung der Scheibe, die Libration und die Sonne und Phase, vom Terminator abgelesen. Nahaufnahmen löst er zuverlässig bis hinab zu Regionen von etwa 250 km Breite; ein Feld unter etwa 150 km, ein Krater, der das Bild füllt, kommt oft als unsure zurück. Das Bild wird im Arbeitsspeicher dekodiert und gelöst und nicht behalten.

Parameter
image
stringerforderlich
Das Foto, Base64-kodiert (Standard- oder URL-sicheres Alphabet; ein Präfix data:image/…;base64, ist in Ordnung). Höchstens 20 MB dekodiert und 120 Megapixel. Formate: JPEG, PNG (8/16 Bit), TIFF, WebP, BMP und GIF; Farbe wird in Luminanz umgewandelt, 16-Bit-Daten werden über ihr hellstes Pixel gestreckt. Die Pixel werden gelesen, wie sie gespeichert sind (eine EXIF-Orientierung wird nicht angewendet), sodass die Antwort zu dem passt, was ein Bildbetrachter zeigt, der sie ignoriert.
Anfrage
{
  "image": "/9j/4AAQSkZJRgABAQEASABIAAD…"
}
Felder
solved
boolean
Ob der Mond mit einem anderen Urteil als unsure gefunden wurde. Ein Foto ohne Mond ist trotzdem eine 200-Antwort, mit solved: false und einem error.
verdict
string
verified: eine sichere Antwort, die die Gegenprüfungen bestanden hat (eine Nahaufnahme liegt deutlich über der zweitbesten Antwort des Fotos und stimmt mit dem Mondrand überein, wenn einer im Bild ist). plausible: wahrscheinlich, aber nicht bestätigt. unsure: nicht gelöst; die beste Vermutung steht trotzdem in view, für das, was sie wert ist.
Erlaubt verified · plausible · unsure
path
string
Wie gelöst wurde: über den Mondrand der Scheibe (der ganze Mond oder ein großer Teil davon im Bild) oder über die Nahaufnahmesuche auf der Vorderseite.
Erlaubt disk · closeup · none
confidence
number
Der Anteil der bandpassgefilterten Energie des Fotos, den das Beleuchtungsmodell bei der Antwort erklärt.
Erlaubt 0–1
runner_up
number
Dasselbe Maß für die beste andere Antwort (ein anderer Ort, eine andere Drehung, ein anderer Maßstab oder eine andere Parität).
width, height
integer
Die Bildgröße in Pixeln. Jeder Pixelwert unten bezieht sich auf dieses Bild.
view
object | null
Die Scheibe im Foto, null, wenn nichts gefunden wurde: cx, cy, R sind Mitte und Radius der Scheibe in Pixeln (0-basierte Pixelmitten; bei einer Nahaufnahme liegen sie weit außerhalb des Bildes); rho ist der Bildwinkel des lunaren Nordens, Grad gegen den Uhrzeigersinn vom Oben des Bildes; par ist 1 bei einer direkten Ansicht und -1 bei einer gespiegelten; lon0, lat0 sind der subterrestrische Punkt in selenografischen Grad (Länge nach Osten positiv), also die Libration.
scale_km_px
number
Kilometer pro Pixel in der Scheibenmitte: 1737,4 km geteilt durch R.
sun
object | null
Der subsolare Punkt, {lon, lat, score, terminator}, vom Foto abgelesen: wo beleuchteter und unbeleuchteter Boden im Bild aneinandergrenzen, die Sonnenlänge, die am besten vorhersagt, was wo ist (lat ist 0; der wahre Wert liegt immer innerhalb von 1,6°); score ist der Anteil der Stichproben des Bildes, die sie richtig vorhersagt. Eine ganze Scheibe ohne Terminator ist ein Vollmond (terminator: false, die Sonne im subterrestrischen Punkt). null bei einer Nahaufnahme ohne Terminator: Die Phase lässt sich daraus nicht ablesen.
phase
object | null
Aus view und sun: angle_deg (der Phasenwinkel: 0 voll, 180 neu), fraction (beleuchtet), waxing, colongitude (die selenografische Kolongitude der Sonne: 0 im ersten Viertel, 90 bei Vollmond, 180 im letzten Viertel) und name (new moon, waxing crescent, first quarter, waxing gibbous, full moon, waning gibbous, last quarter, waning crescent). null ohne sun.
limb
object | null
Der helle Rand der Scheibe, wie im Foto gemessen, {cx, cy, R, arc, refined, locked} (Pixel wie in view; arc ist der Anteil des Kreises, der gemessen wurde), null, wenn kein Mondrand gefunden wurde. locked: true heißt, der Kreis der Ansicht ist dieser Rand; sonst hat die Oberflächentextur die Kugel selbst platziert, die innerhalb des ausgeblühten Randes eines überbelichteten Mondes sitzt.
frame
object | null
Die selenografischen Koordinaten unter dem Bild: center und corners (top-left, top-right, bottom-right, bottom-left), jede {lon, lat} oder null, wo der Punkt neben der Scheibe liegt (die Ecken eines Ganzscheibenfotos).
stats
object
hyps (von der Nahaufnahmesuche geprüfte Positionen) und octaves (durchsuchte Maßstabsoktaven); beide 0, wenn der Mondrand es entschieden hat.
timing_ms
object
decode, limb, disk, closeup, solve und die Gesamtzeit des servers, in Millisekunden.
image
object
format (wie der Decoder es nennt: JPEG, PNG, …), width, height.
error
string
Warum es keine Lösung gibt (wenn solved false ist).
api_version
string
1.0
Antwort (eine Nahaufnahme von Sinus Iridum bei Sonnenaufgang)
{
  "api_version": "1.0",
  "solved": true,
  "verdict": "verified",
  "path": "closeup",
  "confidence": 0.7642,
  "runner_up": 0.0223,
  "width": 1560,
  "height": 1075,
  "view": { "cx": -602.996, "cy": 3686.543, "R": 4399.212, "rho": 305.2046, "par": 1, "lon0": 5.727, "lat0": 4.9752 },
  "scale_km_px": 0.39493,
  "sun": { "lon": 56.5, "lat": 0.0, "score": 0.9505, "terminator": true },
  "phase": { "angle_deg": 50.95, "fraction": 0.815, "waxing": true, "colongitude": 33.5, "name": "waxing gibbous" },
  "limb": null,
  "frame": {
    "center": { "lon": -29.9219, "lat": 46.1421 },
    "corners": [{ "lon": -46.2102, "lat": 39.6896 }, { "lon": -62.682, "lat": 64.4227 }, { "lon": -13.7619, "lat": 52.7875 }, { "lon": -22.696, "lat": 31.4166 }]
  },
  "stats": { "hyps": 864, "octaves": 3 },
  "timing_ms": { "limb": 10.6, "disk": 181.8, "closeup": 145.4, "solve": 337.7, "decode": 5.4, "server": 347.9 },
  "image": { "format": "JPEG", "width": 1560, "height": 1075 }
}

Um auf dem Foto zu zeichnen, projiziere einen selenografischen Punkt (lon, lat) mit der Ansicht: mit p = (cos lat cos lon, cos lat sin lon, sin lat), e_z demselben Vektor für (lon0, lat0), e_y der Mondachse, senkrecht zu e_z gemacht, und e_x = e_y × e_z: X = par · p·e_x, Y = p·e_y, x = cx + R (X cos ρ − Y sin ρ), y = cy − R (X sin ρ + Y cos ρ); der Punkt liegt auf der sichtbaren Seite, wenn p·e_z > 0.

Ein gelöstes Bild beschriften

POST/api/v1/annotate30 auf einmal · 30 pro Minute

Zeichnet das Koordinatengitter, die Sternbilder, die Deep-Sky-Objekte (20.000 davon: Messier, NGC, IC, Sharpless, Barnard, Lynds, van den Bergh, Caldwell, die Sternhaufenkataloge, planetarische Nebel, Supernovaüberreste, die Galaxiengruppen von Arp, Hickson und Abell, RCW und Cederblad), die Sterne mit Namen und Bezeichnungen und, mit einer Uhrzeit, die Sonne, den Mond, die Planeten, Asteroiden und Kometen, so wie Bild speichern in der Werkstatt sie zeichnet: dieselben Objekte, Beschriftungen und Stile. Du schickst das Himmelsmodell, nicht das Bild. Die Beschriftung wird nicht auf den Himmel zugeschnitten: Die Werkstatt findet den Horizont im Foto selbst.

Parameter
sky model
one oferforderlich
Genau eines von corners, wcs, fits_header, projection oder solution: siehe Himmelsmodelle.
width, height
integeroptional
Die Bildgröße in Pixeln. Erforderlich bei corners, wcs und projection; sonst aus solution oder aus NAXIS1/NAXIS2 des FITS-Headers genommen.
Erlaubt 8–100000
format
stringoptional
svg: ein SVG-Dokument in der Größe des Bildes, transparent, zum Darüberlegen. json: die Objekte, Körper, Linien und platzierten Beschriftungen als Daten (JSON-Ausgabe).
Standard "svg"Erlaubt svg · json
time
stringoptional
Wann das Foto aufgenommen wurde (ISO 8601 mit Offset oder Z). Damit werden die Sonne, der Mond, die Planeten und Pluto dort gezeichnet, wo sie standen (innerhalb von 1″ für 1850–2150), und die helleren Asteroiden und die Kometen (innerhalb von etwa 1″ für 1990–2041).
location
objectoptional
Wo es aufgenommen wurde: Der Mond verschiebt sich mit dem Standort des Beobachters um bis zu ein Grad (seine Parallaxe). Ohne Standort wird der Mond so platziert, wie er vom Erdmittelpunkt aus zu sehen wäre.
└lat
numbererforderlich
Breite, Grad nördlich.
Erlaubt -90–90
└lon
numbererforderlich
Länge, Grad östlich.
Erlaubt -180–180
└height
numberoptional
Meter über dem Meeresspiegel.
Erlaubt -500–10000
layout_width
integeroptional
Die Beschriftung wird so angeordnet, als wäre das Foto so viele Pixel breit, und dann auf seine Größe skaliert: Linienstärken und Schriftgrößen sind Pixel dieser Ansicht. Größer: kleinere Beschriftungen und mehr davon.
Standard 1400Erlaubt 200–8000
detail
numberoptional
Wie viel mehr gezeigt wird, so wie Hineinzoomen in der Werkstatt: 0 die Standardauswahl (markante Objekte), 1 jedes Objekt, das der Filter durchlässt.
Standard 0Erlaubt 0–1
view
objectoptional
Ebenen und Stile: siehe Optionen.
filter
objectoptional
Welche Gruppen und Helligkeiten gezeigt werden: siehe Optionen.
edits
objectoptional
Einzelne ausgeblendete oder umbenannte Objekte: siehe Optionen.
Anfrage
{
  "solution": { "width": 2048, "height": 1366, "wcs": { … }, … },
  "format": "svg",
  "time": "2025-08-16T23:00:00+02:00",
  "location": { "lat": 52.23, "lon": 21.01 },
  "view": { "group_by": "catalog", "grid": { "on": false }, "catalogs": { "solar": { "color": "#ff8800", "size": 16 } } },
  "filter": { "catalogs": { "ldn": false, "lbn": false }, "magnitude": [-2, 10] },
  "edits": { "hidden": ["Mars"], "names": { "NGC 1499": "California" } }
}

Mit format: "svg" ist die Antwort image/svg+xml: <svg width="2048" height="1366" viewBox="0 0 2048 1366">…, in den Pixeln des Fotos. Eine Warnung zum Himmelsmodell, falls es eine gibt, kommt im Header SkySolver-Warning.

Himmelsmodelle

Schick das, das du hast; alle beschreiben, wie die Pixel des Bildes auf den Himmel abgebildet werden.

eines von
corners
object
Der Himmel in der Mitte des Bildes und an seinen vier äußeren Ecken, jeweils {ra, dec}: center, top_left, top_right, bottom_right, bottom_left. Eine gnomonische Projektion (TAN) wird daran angepasst; bei verzeichnenden Weitwinkelobjektiven warnt die Antwort, wie weit die Ecken davon abweichen. Jede Ecke muss weniger als 87° von der Mitte entfernt sein: Weitere Ansichten brauchen die projection des Solvers.
wcs
object
TAN oder TAN-SIP, wie der Solver es liefert: crval [RA, Dec], crpix [x, y] (0-basiert), cd [[CD1_1, CD1_2], [CD2_1, CD2_2]] in Grad pro Pixel und optional sip {order, a, b, inv_order, ap, bp} mit Termen [p, q, coefficient].
fits_header
string
Ein FITS-WCS-Header als Text (80-Zeichen-Karten oder eine Karte je Zeile): CTYPE1 = 'RA---TAN' oder 'RA---TAN-SIP', CRVAL, CRPIX (1-basiert, wie in FITS) und CD, oder PC mit CDELT, oder CDELT mit CROTA2; SIPs A_*, B_*, AP_*, BP_*. Was astrometry.net, ASTAP, PixInsight und dieser Solver schreiben.
projection
object
Das Projektionsmodell des Solvers (Panoramen, Fisheye- und Ganzhimmelbilder), wie /solve es liefert.
solution
object
Eine ganze /solve-Antwort: ihre Größe und ihr wcs oder ihre projection werden verwendet.

JSON-Ausgabe

Mit format: "json": was die Beschriftung zeichnet, in Bildpixeln (0-basiert, y nach unten), und die Beschriftungen, wie platziert.

Felder
width, height
integer
Die Bildgröße, für die die Beschriftung gezeichnet wurde.
field
object
center {ra, dec}, scale_arcsec (in der Mitte), diagonal_deg (null bei Ganzhimmelansichten).
layout
object
width (die verwendete layout_width) und scale: Bildpixel je Layout-Pixel, womit Größen und Stärken multipliziert wurden.
objects
array
Die Deep-Sky-Objekte, die Filter und Ansicht auswählen, ausgeblendete eingeschlossen (shown: false).
└id, label
string
Bezeichnung (M 42, NGC 1977), wie edits sie nimmt, und die gezeichnete Beschriftung (M42).
└name, catalogue_name
string | null
Der gezeichnete Name (Orion Nebula oder der in edits angegebene) und der des Katalogs.
└type, group, catalogs
string, string, array
Lesbarer Typ, seine Gruppe (emission…) und jede Kataloggruppe, zu der er gehört.
└other_designations
array
Seine weiteren Bezeichnungen: ["Mel 22", "LBN 770"].
└ra, dec, mag
number
Position und Helligkeit (null, wenn unbekannt).
└size_arcmin, position_angle
array, number
[major, minor] und der Winkel von Norden nach Osten, wenn bekannt.
└x, y, radius_px
number
Wo es im Bild liegt, und sein Radius in Pixeln.
└outline, closed
array | null, boolean
Seine Form als Ringe [x0, y0, x1, y1, …] in Pixeln (ein nachgezeichneter Umriss oder die Ellipse des Katalogs); closed ist false, wenn die Form den Bereich einer Ganzhimmelansicht verlässt und nur Stücke davon gezeichnet werden.
└shown
boolean
false, wenn edits.hidden es ausblendet.
bodies
array
Mit time: die Sonne, der Mond, die Planeten, Asteroiden und Kometen im Bild: id, name, kind (star, moon, planet, dwarf planet, asteroid, comet), ra, dec, mag (bei einem Kometen eine grobe Vorhersage), diameter_arcsec (null bei Asteroiden und Kometen), distance_au, phase (beleuchteter Anteil), elongation_deg, topocentric (platziert wie von location aus gesehen), uncertainty_arcsec (Asteroiden und Kometen: wie weit die Position danebenliegen kann), x, y, radius_px, outline, shown.
constellations
array
id, name, lines (Polylinien in Pixeln), stars, label_at.
grid
array
RA- und Dec-Linien: kind (ra oder dec), value (Grad), label, lines.
lines
array
Die eingeschalteten Bezugslinien: kind (ecliptic, galactic, borders), lines, label_at.
labels
array
Jede Beschriftung, wie platziert, frei von den anderen: text, of (das Objekt), kind, x, y (der Grundlinienanker des Textes), size, anchor (start, middle, end), color, opacity.
warnings, time, location
array, string, object
Warnungen zum Himmelsmodell; die verwendete Zeit (UTC) und der verwendete Ort.

Optionen

Alle optional und unvollständig erlaubt: Was du weglässt, behält die Standardwerte der Werkstatt. Werte außerhalb des Bereichs und Keys, die es nicht gibt, werden mit 422 abgelehnt statt ignoriert.

view
group_by
stringoptional
Objekte werden nach Typ oder nach Katalog gestaltet und gefiltert: types oder catalogs unten gelten dann.
Standard "type"Erlaubt type · catalog
grid
objectoptional
Das RA/Dec-Gitter: on und ein Linienstil (Standard #96beff, gestrichelt).
constellations
objectoptional
Strichfiguren und Namen: on und ein Linienstil.
borders
objectoptional
Die IAU-Sternbildgrenzen (Delporte 1930, auf J2000 präzediert): on (standardmäßig aus) und ein Linienstil.
ecliptic, galactic
objectoptional
Die Ekliptik und der galaktische Äquator, mit ihren Namen: on (standardmäßig aus) und ein Linienstil.
shadow
objectoptional
Ein Schlagschatten unter der ganzen Beschriftung: on (standardmäßig aus), color, opacity, blur (0–16 px), distance (0–12 px).
objects
booleanoptional
Die Objekte zeichnen (und die Sonne, den Mond, die Planeten, Asteroiden und Kometen).
Standard true
labels
booleanoptional
Die Beschriftungen zeichnen.
Standard true
types
objectoptional
Ein Linienstil je Typgruppe, mit den Keys aus Gruppen und Stile: {"emission": {"color": "#ff99cc"}}.
catalogs
objectoptional
Ein Linienstil je Kataloggruppe.
ein Linienstil
color
stringoptional
Farbe von Linien, Markierungen und Beschriftungen.
Erlaubt #rrggbb
opacity
numberoptional
Deckkraft von Linien und Markierungen; Beschriftungen werden etwas deckender gezeichnet.
Erlaubt 0–1
width
numberoptional
Linienstärke, in Pixeln der Layout-Ansicht (siehe layout_width).
Erlaubt 0.3–6
dash
stringoptional
Linienstil.
Erlaubt solid · dashed · dotted · dashdot
size
numberoptional
Schriftgröße der Beschriftungen, in Pixeln der Layout-Ansicht.
Erlaubt 6–32
filter
types
objectoptional
Ein- oder ausgeschaltete Gruppen (mit group_by: "type"): {"dark": false}. Standardmäßig sind alle an.
catalogs
objectoptional
Dasselbe für Kataloge (mit group_by: "catalog").
magnitude
string | arrayoptional
auto: Messier-Objekte immer, andere danach, wie markant sie im Bild sind (Größe, oder eine Helligkeitsgrenze, die dem Bildmaßstab folgt). Ein Bereich: Objekte mit einer Helligkeit darin; die ohne (die meisten Nebel) nach Größe.
Standard "auto"Erlaubt "auto" · [brightest, faintest] within -2–18
edits
hidden
arrayoptional
Objekte, die weggelassen werden, nach Bezeichnung, wie objects[].id sie liefert: ["NGC 1999", "Mars"].
names
objectoptional
Namen, mit denen Objekte beschriftet werden: {"NGC 1499": "California"}; eine leere Zeichenkette beschriftet ein Objekt nur mit seiner Bezeichnung.

Gruppen und Stile

Die Keys von view.types, filter.types, view.catalogs und filter.catalogs, mit ihrem Standardstil (Farbe, Deckkraft, Stärke, Linie, Schriftgröße):

types-KeyGruppeStandard
galaxyGalaxien#f4b8700.75 · 1 px · solid · 10.5 px
openOffene Sternhaufen#86d3f30.75 · 1 px · solid · 10.5 px
globularKugelsternhaufen#f3dc8e0.78 · 1 px · solid · 10.5 px
emissionEmissionsnebel#d4a5ff0.78 · 1 px · solid · 10.5 px
reflectionReflexionsnebel#9cc3ff0.75 · 1 px · solid · 10.5 px
planetaryPlanetarische Nebel#7ee8c60.78 · 1 px · solid · 10.5 px
snrSupernovaüberreste#ff9eb40.75 · 1 px · solid · 10.5 px
darkDunkelnebel#b5c0d40.45 · 1 px · solid · 10.5 px
starSterne#fde9b00.7 · 0.9 px · solid · 10 px
solarSonnensystem#e4f68e0.85 · 1.2 px · solid · 12 px
otherSonstige#dce3f00.65 · 1 px · solid · 10.5 px
catalogs-KeyGruppeStandard
messierMessier#f7cf4a0.85 · 1 px · solid · 12 px
ngcNGC#86d3f30.75 · 1 px · solid · 10.5 px
icIC#aab8ff0.75 · 1 px · solid · 10.5 px
sharplessSharpless (Sh2)#d4a5ff0.78 · 1 px · solid · 10.5 px
barnardBarnard (B)#b5c0d40.5 · 1 px · solid · 10.5 px
ldnLynds dunkel (LDN)#93a1b80.45 · 1 px · solid · 10.5 px
lbnLynds hell (LBN)#f7a8d30.72 · 1 px · solid · 10.5 px
vdbvan den Bergh (vdB, vdBH)#9cc3ff0.75 · 1 px · solid · 10.5 px
caldwellCaldwell#7ee8c60.75 · 1 px · solid · 10.5 px
clustersSternhaufen (Collinder, Melotte, Trumpler, …)#a5e4f70.72 · 1 px · solid · 10.5 px
pnPlanetarische Nebel (PN G, PK, Abell)#7ee8c60.78 · 1 px · solid · 10.5 px
snrSupernovaüberreste (SNR G)#ff9eb40.75 · 1 px · solid · 10.5 px
groupsGalaxiengruppen (Arp, Hickson, Abell/ACO)#f4c48a0.7 · 1 px · solid · 10.5 px
rcwWeitere Nebel (RCW, Gum, Cederblad, DWB)#e0b3ff0.72 · 1 px · solid · 10.5 px
starsSterne (Namen, Bayer, Flamsteed, HR, HD)#fde9b00.7 · 0.9 px · solid · 10 px
customDeine Kataloge (Dateien)#ffb86b0.85 · 1 px · solid · 11 px
vizierOnline (VizieR)#9fe8700.7 · 0.9 px · solid · 9.5 px
solarSonnensystem#e4f68e0.85 · 1.2 px · solid · 12 px
otherSonstige#dce3f00.65 · 1 px · solid · 10.5 px

Fehler

Jede Fehlerantwort hat dieselbe Form: einen Code, auf den man reagieren kann, und eine Meldung zum Anzeigen. Ungültige Anfragen listen jedes Problem auf:

422
{
  "error": "invalid_request",
  "message": "view.grid.color: String should match pattern '^#[0-9a-fA-F]{6}$'",
  "details": [
    { "field": "view.grid.color", "problem": "String should match pattern '^#[0-9a-fA-F]{6}$'" },
    { "field": "filter.magnitude", "problem": "magnitude must be \"auto\" or [brightest, faintest] within -2..18" }
  ]
}
StatuserrorWann
400invalid_imageDas Bild ist kein gültiges Base64 oder lässt sich nicht lesen.
400unsupported_formatDie Datei hat keines der Formate oben.
413payload_too_largeDer Anfragekörper, die Datei oder ihre Pixelzahl liegt über der Grenze.
422invalid_requestEin Feld fehlt, hat den falschen Typ, liegt außerhalb des Bereichs oder ist unbekannt; details listet jedes auf.
429rate_limitedDeine Client-Adresse hat ihre Anfragen aufgebraucht; retry_after sagt, wann du es wieder versuchen kannst.
429busyDer Server löst so viel er kann; versuch es nach Retry-After noch einmal.
500internal_errorAuf unserer Seite ist etwas fehlgeschlagen.
503unavailableDer Solver, der Mond-Solver oder der Annotator ist nicht bereit.

Ein Bild, das sich nicht lösen lässt, ist kein Fehler: Die Antwort ist 200 mit solved: false.

Health

GET/api/v1/health60 auf einmal · 60 pro Minute

Der Status des Dienstes, die geladenen Sternindizes, der Mond-Solver und die Annotator-Worker sowie die geltenden Grenzen.

Antwort
{
  "status": "ok",
  "version": "1.0",
  "uptime_s": 86400.2,
  "solver": { "indexes": 4, "max_concurrent": 4, "in_flight": 0 },
  "moon": { "ready": true },
  "annotator": { "ok": true, "workers": 2, "objects": 15333 },
  "limits": {
    "rates": {
      "image": { "burst": 10, "per_minute": 1 },
      "moon": { "burst": 20, "per_minute": 10 },
      "stars": { "burst": 30, "per_minute": 30 },
      "annotate": { "burst": 30, "per_minute": 30 },
      "light": { "burst": 60, "per_minute": 60 }
    },
    "image_mb": 20, "megapixels": 120, "stars": 10000, "time_limit_ms": 30000
  }
}

Astrometry.net-kompatible API

Programme, die online mit astrometry.net (nova.astrometry.net) plate-solven, können stattdessen SkySolver nutzen: Stell ihren Server auf https://skysolver.app. Jeder API-Schlüssel funktioniert, auch ein leerer; es gibt keine Konten. Die Routen, die Antworten und die Dateien sind die von nova, bis in die Details, auf die sich seine Clients verlassen, an der Wurzel der Website (/api/…, /wcs_file/…).

ProgrammEinstellung
N.I.N.A.Options → Plate solving → Astrometry.net: URL https://skysolver.app, beliebiger API-Schlüssel
KStars / EkosAlign → solver options → Online (astrometry.net): API URL https://skysolver.app (https: StellarSolver ergänzt es ohnehin), beliebiger Schlüssel
astroqueryAstrometryNet() mit URL = "https://skysolver.app", API_URL = "https://skysolver.app/api", beliebiger api_key
client.py (astrometry.net)--server https://skysolver.app/api/ --apikey anything; das Online-Skript von CCDciel verwendet es
AstroImageJPlate solve → custom server https://skysolver.app, Schlüssel leer
SGPder ANSVR-Solver, Server URL https://skysolver.app/api (die Routen, die SGP aufruft, sind da; mit SGP selbst nicht getestet)
astroquery
from astroquery.astrometry_net import AstrometryNet

ast = AstrometryNet()
ast.URL, ast.API_URL, ast.api_key = "https://skysolver.app", "https://skysolver.app/api", "anything"
wcs_header = ast.solve_from_image("m31.jpg")            # or ast.solve_from_source_list(x, y, width, height)
RouteWas sie hier tut
POST /api/loginEine Sitzung für jeden Schlüssel.
POST /api/uploadEin Bild (JPEG, PNG, TIFF, FITS, XISF, BMP, GIF, WebP), eine x,y-Liste (eine FITS-Tabelle mit X und Y, oder Text mit einem x y je Zeile) oder x- und y-Listen in request-json. Bis 96 MB.
POST /api/url_uploadNur x- und y-Listen (wie astroquery sie sendet): Eine URL wird nicht abgerufen.
/api/submissions/IDDie Einreichung und ihr Job: Der Job ist ab der ersten Abfrage da.
/api/jobs/IDprocessing, solving, success oder failure; jeder Job endet in einem der letzten beiden.
/api/jobs/ID/calibration/ra, dec, radius, pixscale, orientation, parity, width_arcsec, height_arcsec, berechnet wie bei nova.
/api/jobs/ID/info/ · tags/ · machine_tags/ · objects_in_field/ · annotations/Die Deep-Sky-Objekte im Feld, mit ihren Pixelpositionen und Radien in annotations.
/wcs_file/IDDie TAN-SIP-Lösung als FITS-Datei nur mit Header (wcs.fits).
/corr_file/ID · /axy_file/ID · /rdls_file/IDDie zugeordneten Sterne, die erkannten Sterne, die zugeordneten Katalogsterne: FITS-Tabellen in novas Spalten.
/joblog/IDWas der Job getan hat, als Text.
  • Immer blind. Hinweise zu Maßstab, Position und Parität werden angenommen und ignoriert: Der Solver braucht keine, und ein falscher Hinweis kann keine Lösung verderben.
  • Pixel sind die von nova: (1, 1) ist die Mitte des ersten gespeicherten Pixels, oben links bei einem JPEG oder PNG (seine EXIF-Orientierung nicht angewendet) oder die erste Zeile einer FITS-Datei, was auch immer ihr ROWORDER sagt. Die orientation behält novas Eigenheit bei JPEG-, PNG- und GIF-Uploads, sodass die Programme, die sie zurückrechnen, denselben Winkel bekommen wie von nova.
  • Panoramen und Ganzhimmelbilder, die mit einem Projektionsmodell gelöst wurden, haben eine calibration, aber keine wcs_file: Kein TAN-SIP erfasst sie.
  • Keine Bilder werden behalten. Ein Upload wird verworfen, sobald seine Sterne gefunden sind, also werden new_fits_file und die beschrifteten, Rot-Grün- und Extraktionsbilder nicht angeboten. Die Ergebnisse eines Jobs bleiben 30 Minuten im Arbeitsspeicher, dann sind sie vergessen.
  • Grenzen: Uploads 20 auf einmal und 6 pro Minute je Adresse; die anderen Routen zählen als leichte Anfragen (60 auf einmal, 60 pro Minute).

Änderungen

  • 1.2 (19. Oktober 2026): Mondfotos lösen: /api/v1/solve/moon.
  • 1.1 (17. Oktober 2026): die Astrometry.net-kompatible API.
  • 1.0 (16. Oktober 2026): ein Bild (Base64) oder Sternpositionen lösen, als SVG oder JSON beschriften, mit Sonne, Mond und Planeten.

Fragen, ein Fehler, ein größeres Kontingent? [email protected]. Mit der Nutzung der API akzeptierst du die Nutzungsbedingungen; was sie mit deinen Daten tut, steht auf der Seite Datenschutz.