API · v1

API SkySolver

Przeprowadź astrometrię zdjęcia nocnego nieba lub listy jego gwiazd i narysuj adnotację, jako SVG do nałożenia na zdjęcie albo jako JSON do samodzielnego narysowania; możesz też rozwiązać zdjęcie Księżyca. To te same solvery i te same adnotacje co w Pracowni. API jest darmowe i nie wymaga klucza, a programy stworzone dla solvera online Astrometry.net, takie jak N.I.N.A. i KStars, mogą z niego korzystać po zmianie jednego adresu: zobacz jak.

Przegląd

Bez klucza
Za darmo i anonimowo: bez konta ani klucza API.
Z limitem zapytań
Na adres klienta, zależnie od wagi zapytania.
Nic nie jest zapisywane
Obrazy, listy gwiazd i wyniki nie są przechowywane ani logowane.
  • Adres bazowy https://skysolver.app/api/v1. Zapytania i odpowiedzi są w formacie JSON (UTF-8); adnotacja może też zostać zwrócona jako SVG.
  • Cztery punkty dostępu: przeprować astrometrię obrazu wysłany jako base64, oblicz pozycje gwiazd zmierzone samodzielnie, rozwiąż astrometrycznie zdjęcie Księżyca i opisz obraz.
  • CORS jest otwarty: API można wywoływać ze strony internetowej.
  • Wersje: zmiany niezgodne wstecz dostają nową ścieżkę (/api/v2); v1 zyskuje tylko opcjonalne pola. Dokument OpenAPI opisuje każdy model.
  • Uczciwe użycie: usługa jest darmowa i działa na małym serwerze. Przy dużych partiach optymalnie wykrywać listy gwiazd samodzielnie. W przypadku większego zapotrzebowania napisz na [email protected].

Szybki start

Przeprowadź astrometrię zdjęcia, a potem pobierz jego adnotację jako SVG w rozmiarze zdjęcia, do nałożenia:

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

To samo w JavaScripcie (Node 18 lub nowszy; w przeglądarce różni się tylko odczyt pliku):

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();
}

I w Pythonie:

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"})

Limity

Każdy adres klienta ma pulę zapytań na każdy punkt dostępu: do burst naraz, uzupełnianą w stałym tempie. Zapytanie po przekroczeniu jest od razu odrzucane z kodem 429 i Retry-After. Każda odpowiedź aktualizuje RateLimit-Limit (burst), RateLimit-Remaining, RateLimit-Reset (sekundy do pełnej puli) i RateLimit-Policy.

EndpointBurstUzupełnianieTreść zapytania
POST /solve/image101 na minutę28 MB (plik 20 MB w base64)
POST /solve/stars3030 na minutę4 MB
POST /solve/moon2010 na minutę28 MB (plik 20 MB w base64)
POST /annotate3030 na minutę2 MB
GET /health6060 na minutę–
  • Obrazy: najwyżej 20 MB i 120 megapikseli. Aplikacja procesuje maksymalnie przez time_limit_ms (1–30 s, domyślnie 12 s). Zdjęcie Księżyca jest rozwiązywane przy najwyżej 2048 pikselach dłuższego boku (większe są najpierw pomniejszane; odpowiedź jest w pikselach pliku) i zajmuje najwyżej kilka sekund.
  • Listy gwiazd: od 5 do 10 000 gwiazd; używane jest 3000 najjaśniejszych.
  • Zajęty: serwer wykonuje kilka rozwiązań naraz (max_concurrent w stanie usługi). Powyżej tego limitu zapytanie jest od razu odrzucane z 429, error: "busy" i Retry-After: odczekaj tyle, plus losową sekundę lub dwie, i wyślij je ponownie.
  • GET /health zwraca obowiązujące limity.

Konwencje

  • Współrzędne nieba to stopnie w ICRS (J2000): RA 0–360, Dec od −90 do 90.
  • Piksele liczone są od 0 w środku lewego górnego piksela; x rośnie w prawo, y w dół. Lewy górny róg obrazu to zatem (−0,5, −0,5), a jego środek (width/2 − 0,5, height/2 − 0,5). FITS liczy od 1: listy gwiazd mogą to zaznaczyć (pixel_origin), a fits_header używa własnej konwencji FITS.
  • Czasy są w ISO 8601 z przesunięciem UTC lub Z: 2024-10-12T21:34:05+02:00. Czas bez tego jest od razu odrzucany.
  • Błędy mają postać {"error": code, "message": text}, z details dla nieprawidłowych pól: zob. Błędy.

Przeprowadź astrometrię zdjęcia

POST/api/v1/solve/image10 naraz · 1 na minutę

Wykrywa gwiazdy na zdjęciu i ustala, w którą stronę jest skierowany: w ciemno, bez żadnych podpowiedzi na temat pozycji, skali czy obrocie, dla pól od kilku minut łuku po panoramy całego nieba. Obraz jest dekodowany i rozwiązywany w pamięci i nie jest zapisywany.

Parametry
image
stringwymagane
Plik obrazu zakodowany w base64 (alfabet standardowy lub URL-safe; prefiks data:image/…;base64, jest w porządku). Najwyżej 20 MB po zdekodowaniu i 120 megapikseli. Formaty: JPEG, PNG (8/16 bitów), TIFF (8/16/32 bity i zmiennoprzecinkowy; bez kompresji, LZW, ZIP, PackBits), FITS (całkowity lub zmiennoprzecinkowy; mono, RGB albo surowa mozaika kamery kolorowej), XISF (bez kompresji lub zlib), BMP, GIF, TGA i PSD. Dane liniowe (stosy, FITS, XISF) są rozciągane przed wykrywaniem.
time_limit_ms
integeropcjonalne
Jak długo detektor może szukać, zanim się podda.
Domyślnie 12000Dozwolone 1000–30000
zapytanie
{
  "image": "/9j/4AAQSkZJRgABAQEASABIAAD…",
  "time_limit_ms": 12000
}

Odpowiedzią jest rozwiązanie, plus image (format, width, height) i capture: kiedy i gdzie wykonano zdjęcie, według jego metadanych (EXIF, XMP, IPTC, nagłówki FITS, właściwości XISF).

capture
time
object | null
Czas wykonania zdjęcia albo null, gdy plik go nie ma.
└utc
string | null
Chwila w UTC: null, gdy plik podaje wskazanie zegara bez strefy czasowej (EXIF sprzed 2.31, XMP z Lightrooma).
└local
string
Wskazanie zegara tak, jak zapisano: czas lokalny aparatu dla EXIF, UTC dla FITS.
└utc_offset
string | null
Przesunięcie zegara, +02:00; null, gdy nieznane.
└source
string
Skąd odczytano: EXIF DateTimeOriginal, FITS DATE-OBS, XISF Observation:Time:Start…
└exposure_s
number
Ekspozycja (albo od pierwszego początku do ostatniego końca stosu), gdy znana; czas jest wtedy jej środkiem.
└note
string
Coś do sprawdzenia: stos datowany jedną ze swoich klatek, aparat, który mógł nie mieć ustawionej strefy.
└date_only
boolean
true, gdy plik podaje datę bez godziny.
location
object | null
Gdzie wykonano zdjęcie, z GPS lub słów kluczowych FITS o miejscu obserwacji: {lat, lon, height, source}, stopnie na wschód i północ, metry.
other_dates
array
Inne daty w pliku, które mogą nie być czasem wykonania zdjęcia (utworzenie, modyfikacja), o kształcie jak time.
odpowiedź (skrócona)
{
  "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": []
  }
}

Rozwiąż pozycje gwiazd

POST/api/v1/solve/stars30 naraz · 30 na minutę

Rozwiązuje z pozycji gwiazd zmierzonych samodzielnie (SExtractor, SEP, photutils, StarDetector z PixInsight, własne centroidy): obraz nigdy nie opuszcza twojej maszyny, a zapytanie ma kilka kilobajtów. Tak rozwiązuje Pracownia.

Parametry
width
integerwymagane
Szerokość obrazu w pikselach.
Dozwolone 8–100000
height
integerwymagane
Wysokość obrazu w pikselach.
Dozwolone 8–100000
stars
arraywymagane
Pozycje gwiazd, każda jako [x, y], [x, y, flux] albo {"x": …, "y": …, "flux": …}. flux to dowolna dodatnia miara jasności (suma, szczyt, …): podaj go dla każdej gwiazdy albo dla żadnej, a bez niego wymień gwiazdy od najjaśniejszej. 30 do 300 gwiazd w zupełności wystarczy; używane jest 3000 najjaśniejszych. Pozycje muszą leżeć w obrazie.
Dozwolone 5–10000 items
pixel_origin
integeropcjonalne
0: środek pierwszego piksela to (0, 0), jak w numpy i OpenCV. 1: to (1, 1), jak w FITS, SExtractorze, astrometry.net i DS9. Odpowiedzi są zawsze liczone od 0.
Domyślnie 0Dozwolone 0 · 1
time_limit_ms
integeropcjonalne
Jak długo program może szukać.
Domyślnie 12000Dozwolone 1000–30000
zapytanie
{
  "width": 6000,
  "height": 4000,
  "stars": [
    [3735.37, 69.14, 51230],
    [2120.04, 1987.51, 48810],
    { "x": 812.6, "y": 3020.9, "flux": 47002 },
    …
  ]
}

Odpowiedzią jest rozwiązanie.

Rozwiązanie

Oba endpointy pól gwiazdowych odpowiadają tym obiektem.

pola
solved
boolean
Czy znaleziono rozwiązanie. Zdjęcie, którego nie da się rozwiązać, to nadal odpowiedź 200, z solved: false i error.
width, height
integer
Rozmiar obrazu w pikselach.
center
object | null
Niebo w środku obrazu: {ra, dec} w stopniach. null, gdy środek obrazu całego nieba nie leży na niebie.
corners
array
Cztery zewnętrzne rogi obrazu, top-left, top-right, bottom-right, bottom-left: każdy {name, x, y, ra, dec}, z ra i dec null tam, gdzie róg jest poza niebem.
fov
object
{width_deg, height_deg}: kątowa długość poziomej i pionowej linii środkowej obrazu.
scale_arcsec
number
Sekundy łuku na piksel w środku.
rotation_deg
number
Dokąd wskazuje góra obrazu: stopnie od północy przez wschód (0: północ u góry, 90: wschód u góry).
parity
string
Obrazy odbite lustrzanie (odwrócone w obróbce albo przez przekątną) też są rozwiązywane.
Dozwolone normal · mirrored
wcs
object | null
Rozwiązanie jako TAN lub TAN-SIP: crval (RA, Dec piksela odniesienia), crpix (piksel odniesienia, liczony od 0), cd (stopnie na piksel) i sip (wielomiany dystorsji, wyrazy [p, q, coefficient]). null dla rozwiązań projekcyjnych.
projection
object | null
Rozwiązanie jako model projekcji, dla panoram, obiektywów fisheye i widoków całego nieba, których nie oddaje żaden TAN-SIP; null w przeciwnym razie. Przekaż go, albo całe rozwiązanie, do /annotate.
stats
object
stars (wykryte lub podane), matches, rms_px (jak daleko dopasowane gwiazdy leżą od modelu), log_odds (świadectwo dopasowania, logarytm naturalny: rozwiązanie wymaga 25 i 10 dopasowanych gwiazd) oraz szczegóły szukania.
fits_header
string | null
Rozwiązanie TAN-SIP jako nagłówek FITS WCS (karty 80-znakowe; CRPIX liczony od 1, jak w FITS), gotowy do scalenia z plikiem FITS. null dla rozwiązań projekcyjnych.
matched
array
Gwiazdy katalogowe (Gaia DR3) dopasowane przez rozwiązanie, do kilku tysięcy: każda [x, y, ra, dec, magnitude], jasność to G z Gai.
timing_ms
object
decode (odczyt pliku), detect, solve oraz łączny czas server dla zapytania, w milisekundach.
error
string
Dlaczego nie ma rozwiązania (gdy solved jest false).
api_version
string
1.0

Rozwiąż zdjęcie Księżyca

POST/api/v1/solve/moon20 naraz · 10 na minutę

Znajduje Księżyc na zdjęciu i dopasowuje jego tarczę: w ciemno, w dowolnej skali, obrocie i odbiciu, w dowolnej fazie, niezależnie od tego, czy kadr obejmuje całą tarczę, jej część czy zbliżenie kilku kraterów. Zdjęcie po filtracji pasmowej jest dopasowywane, w każdej pozycji, obrocie i parzystości, jako mieszanka trzech stałych map widocznej strony (albedo i jego dwóch nachyleń), czyli tego, co dowolny kierunek Słońca robi z powierzchnią; ułamek zdjęcia, który mieszanka wyjaśnia, jest pewnością, a brzeg tarczy, gdy jest, ustala librację. Odpowiedź umieszcza każdy punkt zdjęcia na Księżycu: środek, promień i orientację tarczy, librację oraz Słońce i fazę odczytane z terminatora. Zbliżenia rozwiązuje niezawodnie do regionów o szerokości około 250 km; pole poniżej około 150 km, jeden krater wypełniający kadr, często wraca jako unsure. Obraz jest dekodowany i rozwiązywany w pamięci i nie jest zachowywany.

Parametry
image
stringwymagane
Zdjęcie zakodowane w base64 (alfabet standardowy lub URL-safe; prefiks data:image/…;base64, jest w porządku). Najwyżej 20 MB po zdekodowaniu i 120 megapikseli. Formaty: JPEG, PNG (8/16 bitów), TIFF, WebP, BMP i GIF; kolor jest zamieniany na luminancję, dane 16-bitowe rozciągane do najjaśniejszego piksela. Piksele są czytane tak, jak zapisano (orientacja EXIF nie jest stosowana), więc odpowiedź zgadza się z tym, co pokazuje przeglądarka obrazów, która ją ignoruje.
zapytanie
{
  "image": "/9j/4AAQSkZJRgABAQEASABIAAD…"
}
pola
solved
boolean
Czy znaleziono Księżyc z werdyktem innym niż unsure. Zdjęcie bez Księżyca to nadal odpowiedź 200, z solved: false i error.
verdict
string
verified: pewna odpowiedź, która przeszła sprawdzenia krzyżowe (zbliżenie wyraźnie góruje nad drugim wynikiem dla tego zdjęcia i zgadza się z brzegiem tarczy, gdy jest w kadrze). plausible: prawdopodobna, ale niepotwierdzona. unsure: nierozwiązane; najlepszy strzał nadal jest podawany w view, na ile jest wart.
Dozwolone verified · plausible · unsure
path
string
Jak rozwiązano: z brzegu tarczy (cały Księżyc lub jego duża część w kadrze) albo przez szukanie zbliżenia po widocznej stronie.
Dozwolone disk · closeup · none
confidence
number
Ułamek energii zdjęcia po filtracji pasmowej, który model oświetlenia wyjaśnia w odpowiedzi.
Dozwolone 0–1
runner_up
number
Ta sama miara dla najlepszej odmiennej odpowiedzi (inne miejsce, obrót, skala lub parzystość).
width, height
integer
Rozmiar obrazu w pikselach. Każda wartość w pikselach poniżej jest w tym układzie.
view
object | null
Tarcza na zdjęciu, null, gdy niczego nie znaleziono: cx, cy, R to środek i promień tarczy w pikselach (środki pikseli liczone od 0; dla zbliżenia leżą daleko poza kadrem); rho to kąt ekranowy księżycowej północy, w stopniach przeciwnie do wskazówek zegara od góry obrazu; par to 1 dla widoku bez odbicia i -1 dla lustrzanego; lon0, lat0 to punkt podobserwatorski w stopniach selenograficznych (długość dodatnia na wschód), czyli libracja.
scale_km_px
number
Kilometry na piksel w środku tarczy: 1737,4 km podzielone przez R.
sun
object | null
Punkt podsłoneczny, {lon, lat, score, terminator}, odczytany ze zdjęcia: tam, gdzie w kadrze oświetlony grunt styka się z nieoświetlonym, długość Słońca, która najlepiej przewiduje, który jest który (lat wynosi 0; prawdziwa wartość mieści się zawsze w 1,6°); score to ułamek próbek kadru, które przewiduje poprawnie. Cała tarcza bez terminatora to pełnia (terminator: false, Słońce w punkcie podobserwatorskim). null dla zbliżenia bez terminatora: nie da się z niego odczytać fazy.
phase
object | null
Z view i sun: angle_deg (kąt fazowy: 0 pełnia, 180 nów), fraction (oświetlona), waxing, colongitude (selenograficzna kolongituda Słońca: 0 w pierwszej kwadrze, 90 w pełni, 180 w ostatniej kwadrze) i name (new moon, waxing crescent, first quarter, waxing gibbous, full moon, waning gibbous, last quarter, waning crescent). null bez sun.
limb
object | null
Jasna krawędź tarczy zmierzona na zdjęciu, {cx, cy, R, arc, refined, locked} (piksele jak w view; arc to udział okręgu, który zmierzono), null, gdy nie znaleziono brzegu. locked: true oznacza, że okrąg widoku to ta krawędź; w przeciwnym razie sferę umieściła sama tekstura powierzchni, a leży ona wewnątrz rozlanej krawędzi prześwietlonego Księżyca.
frame
object | null
Współrzędne selenograficzne pod kadrem: center i corners (top-left, top-right, bottom-right, bottom-left), każdy {lon, lat} albo null tam, gdzie punkt jest poza tarczą (rogi zdjęcia całej tarczy).
stats
object
hyps (pozycje wypróbowane przez szukanie zbliżenia) i octaves (przeszukane oktawy skali); oba 0, gdy rozstrzygnął brzeg tarczy.
timing_ms
object
decode, limb, disk, closeup, solve oraz łączny czas server, w milisekundach.
image
object
format (tak, jak nazywa go dekoder: JPEG, PNG, …), width, height.
error
string
Dlaczego nie ma rozwiązania (gdy solved jest false).
api_version
string
1.0
odpowiedź (zbliżenie Sinus Iridum o wschodzie Słońca)
{
  "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 }
}

Aby rysować na zdjęciu, rzutuj punkt selenograficzny (lon, lat) przez widok: przy p = (cos lat cos lon, cos lat sin lon, sin lat), e_z tym samym wektorze dla (lon0, lat0), e_y osi Księżyca sprowadzonej do prostopadłej do e_z i 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 ρ); punkt jest po widocznej stronie, gdy p·e_z > 0.

Opisz rozwiązany obraz

POST/api/v1/annotate30 naraz · 30 na minutę

Rysuje siatkę współrzędnych, gwiazdozbiory, obiekty głębokiego nieba (20 000: Messier, NGC, IC, Sharpless, Barnard, Lynds, van den Bergh, Caldwell, katalogi gromad gwiazd, mgławice planetarne, pozostałości po supernowych, grupy galaktyk Arp, Hickson i Abell, RCW i Cederblad), gwiazdy z nazwami i oznaczeniami oraz, dla podanego czasu, Słońce, Księżyc, planety, planetoidy i komety, tak jak rysuje je Zapisz obraz w Pracowni: te same obiekty, etykiety i style. Wysyłasz model nieba, nie obraz. Adnotacja nie jest przycinana do nieba: Pracownia sama znajduje horyzont na zdjęciu.

Parametry
sky model
one ofwymagane
Dokładnie jedno z corners, wcs, fits_header, projection lub solution: zob. Modele nieba.
width, height
integeropcjonalne
Rozmiar obrazu w pikselach. Wymagany z corners, wcs i projection; w pozostałych przypadkach brany z solution albo z NAXIS1/NAXIS2 nagłówka FITS.
Dozwolone 8–100000
format
stringopcjonalne
svg: dokument SVG w rozmiarze obrazu, przezroczysty, do nałożenia na zdjęcie. json: obiekty, ciała, linie i rozmieszczone etykiety jako dane (Wyjście JSON).
Domyślnie "svg"Dozwolone svg · json
time
stringopcjonalne
Kiedy wykonano zdjęcie (ISO 8601 z przesunięciem lub Z). Z nim Słońce, Księżyc, planety i Pluton są rysowane tam, gdzie były (z dokładnością 1″ dla lat 1850–2150), a także jaśniejsze planetoidy i komety (z dokładnością około 1″ dla lat 1990–2041).
location
objectopcjonalne
Gdzie wykonano zdjęcie: Księżyc przesuwa się nawet o stopień zależnie od miejsca obserwatora (jego paralaksa). Bez miejsca Księżyc jest umieszczany tak, jak widać go ze środka Ziemi.
└lat
numberwymagane
Szerokość geograficzna, stopnie na północ.
Dozwolone -90–90
└lon
numberwymagane
Długość geograficzna, stopnie na wschód.
Dozwolone -180–180
└height
numberopcjonalne
Metry nad poziomem morza.
Dozwolone -500–10000
layout_width
integeropcjonalne
Adnotacja jest rozmieszczana jak dla zdjęcia pokazanego w tylu pikselach szerokości, a potem skalowana do jego rozmiaru: grubości linii i rozmiary czcionek są pikselami tego widoku. Większa wartość: mniejsze etykiety i więcej ich.
Domyślnie 1400Dozwolone 200–8000
detail
numberopcjonalne
O ile więcej pokazać, tak jak robi to przybliżanie w Pracowni: 0 domyślny wybór (wyraziste obiekty), 1 każdy obiekt, który przepuszcza filtr.
Domyślnie 0Dozwolone 0–1
view
objectopcjonalne
Warstwy i style: zob. Opcje.
filter
objectopcjonalne
Które grupy i jasności pokazać: zob. Opcje.
edits
objectopcjonalne
Pojedyncze obiekty ukryte lub przemianowane: zob. Opcje.
zapytanie
{
  "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" } }
}

Z format: "svg" odpowiedź to image/svg+xml: <svg width="2048" height="1366" viewBox="0 0 2048 1366">…, w pikselach zdjęcia. Ewentualne ostrzeżenie o modelu nieba przychodzi w nagłówku SkySolver-Warning.

Modele nieba

Wyślij ten, który masz; wszystkie opisują, jak piksele obrazu odwzorowują się na niebo.

jedno z
corners
object
Niebo w środku obrazu i w jego czterech zewnętrznych rogach, każdy {ra, dec}: center, top_left, top_right, bottom_right, bottom_left. Dopasowywana jest do nich projekcja gnomoniczna (TAN); dla szerokokątnych obiektywów z dystorsją odpowiedź ostrzega, jak daleko rogi leżą od niej. Każdy róg musi być mniej niż 87° od środka: szersze widoki wymagają projection z solvera.
wcs
object
TAN lub TAN-SIP tak, jak podaje je solver: crval [RA, Dec], crpix [x, y] (liczone od 0), cd [[CD1_1, CD1_2], [CD2_1, CD2_2]] w stopniach na piksel i opcjonalnie sip {order, a, b, inv_order, ap, bp} z wyrazami [p, q, coefficient].
fits_header
string
Nagłówek FITS WCS jako tekst (karty 80-znakowe albo jedna karta na linię): CTYPE1 = 'RA---TAN' lub 'RA---TAN-SIP', CRVAL, CRPIX (liczony od 1, jak w FITS) oraz CD, albo PC z CDELT, albo CDELT z CROTA2; A_*, B_*, AP_*, BP_* SIP. To, co zapisują astrometry.net, ASTAP, PixInsight i ten solver.
projection
object
Model projekcji solvera (panoramy, fisheye i obrazy całego nieba), tak jak zwraca go /solve.
solution
object
Cała odpowiedź /solve: używane są jej rozmiar i jej wcs lub projection.

Wyjście JSON

Z format: "json": to, co rysuje adnotacja, w pikselach obrazu (liczonych od 0, y w dół), oraz etykiety tak, jak je rozmieszczono.

pola
width, height
integer
Rozmiar obrazu, dla którego narysowano adnotację.
field
object
center {ra, dec}, scale_arcsec (w środku), diagonal_deg (null dla widoków całego nieba).
layout
object
width (użyte layout_width) i scale: piksele obrazu na piksel układu, przez który pomnożono rozmiary i grubości.
objects
array
Obiekty głębokiego nieba wybrane przez filtr i widok, razem z ukrytymi (shown: false).
└id, label
string
Oznaczenie (M 42, NGC 1977), tak jak przyjmuje je edits, i narysowana etykieta (M42).
└name, catalogue_name
string | null
Narysowana nazwa (Orion Nebula albo ta podana w edits) i własna nazwa z katalogu.
└type, group, catalogs
string, string, array
Czytelny typ, jego grupa (emission…) i każda grupa katalogowa, do której należy.
└other_designations
array
Jego inne oznaczenia: ["Mel 22", "LBN 770"].
└ra, dec, mag
number
Pozycja i jasność (null, gdy nieznana).
└size_arcmin, position_angle
array, number
[wielka, mała] oraz kąt na wschód od północy, gdy znane.
└x, y, radius_px
number
Gdzie jest na obrazie i jego promień w pikselach.
└outline, closed
array | null, boolean
Jego kształt jako pierścienie [x0, y0, x1, y1, …] w pikselach (obrysowany kontur albo elipsa z katalogu); closed jest false, gdy kształt wychodzi poza dziedzinę widoku całego nieba i rysowane są tylko jego fragmenty.
└shown
boolean
false, gdy ukrywa go edits.hidden.
bodies
array
Z time: Słońce, Księżyc, planety, planetoidy i komety w kadrze: id, name, kind (star, moon, planet, dwarf planet, asteroid, comet), ra, dec, mag (dla komety zgrubna prognoza), diameter_arcsec (null dla planetoid i komet), distance_au, phase (oświetlony ułamek), elongation_deg, topocentric (umieszczone tak, jak widać z location), uncertainty_arcsec (planetoidy i komety: o ile pozycja może być chybiona), x, y, radius_px, outline, shown.
constellations
array
id, name, lines (łamane w pikselach), stars, label_at.
grid
array
Linie RA i Dec: kind (ra lub dec), value (stopnie), label, lines.
lines
array
Włączone linie odniesienia: kind (ecliptic, galactic, borders), lines, label_at.
labels
array
Każda etykieta tak, jak ją rozmieszczono, bez kolizji z innymi: text, of (obiekt), kind, x, y (punkt zaczepienia linii bazowej tekstu), size, anchor (start, middle, end), color, opacity.
warnings, time, location
array, string, object
Ostrzeżenia o modelu nieba; użyty czas (UTC) i miejsce.

Opcje

Wszystkie opcjonalne i częściowe: to, co pominiesz, zachowuje domyślne ustawienia Pracowni. Wartości spoza zakresu i nieistniejące klucze są odrzucane z 422, a nie ignorowane.

view
group_by
stringopcjonalne
Obiekty dostają style i są filtrowane według typu albo według katalogu: stosuje się wtedy odpowiednio types lub catalogs poniżej.
Domyślnie "type"Dozwolone type · catalog
grid
objectopcjonalne
Siatka RA/Dec: on i styl linii (domyślnie #96beff, kreskowana).
constellations
objectopcjonalne
Schematy i nazwy: on i styl linii.
borders
objectopcjonalne
Granice gwiazdozbiorów IAU (Delporte 1930, z precesją do J2000): on (domyślnie wyłączone) i styl linii.
ecliptic, galactic
objectopcjonalne
Ekliptyka i równik galaktyczny, z nazwami: on (domyślnie wyłączone) i styl linii.
shadow
objectopcjonalne
Cień pod całą adnotacją: on (domyślnie wyłączony), color, opacity, blur (0–16 px), distance (0–12 px).
objects
booleanopcjonalne
Rysuj obiekty (oraz Słońce, Księżyc, planety, planetoidy i komety).
Domyślnie true
labels
booleanopcjonalne
Rysuj etykiety.
Domyślnie true
types
objectopcjonalne
Styl linii dla każdej grupy typów, z kluczami jak w Grupy i style: {"emission": {"color": "#ff99cc"}}.
catalogs
objectopcjonalne
Styl linii dla każdej grupy katalogów.
styl linii
color
stringopcjonalne
Kolor linii, znaczników i etykiet.
Dozwolone #rrggbb
opacity
numberopcjonalne
Krycie linii i znaczników; etykiety są rysowane nieco bardziej kryjąco.
Dozwolone 0–1
width
numberopcjonalne
Grubość linii, w pikselach widoku układu (zob. layout_width).
Dozwolone 0.3–6
dash
stringopcjonalne
Rodzaj linii.
Dozwolone solid · dashed · dotted · dashdot
size
numberopcjonalne
Rozmiar czcionki etykiet, w pikselach widoku układu.
Dozwolone 6–32
filter
types
objectopcjonalne
Grupy włączone lub wyłączone (z group_by: "type"): {"dark": false}. Domyślnie wszystkie są włączone.
catalogs
objectopcjonalne
To samo dla katalogów (z group_by: "catalog").
magnitude
string | arrayopcjonalne
auto: obiekty Messiera zawsze, pozostałe według tego, jak wyraziste są w kadrze (rozmiar albo granica jasności zależna od skali obrazu). Zakres: obiekty o jasności w jego granicach; te bez jasności (większość mgławic) według rozmiaru.
Domyślnie "auto"Dozwolone "auto" · [brightest, faintest] within -2–18
edits
hidden
arrayopcjonalne
Obiekty do pominięcia, po oznaczeniu takim, jakie podaje objects[].id: ["NGC 1999", "Mars"].
names
objectopcjonalne
Nazwy, którymi podpisać obiekty: {"NGC 1499": "California"}; pusty łańcuch podpisuje obiekt samym oznaczeniem.

Grupy i style

Klucze view.types, filter.types, view.catalogs i filter.catalogs, z ich domyślnym stylem (kolor, krycie, grubość, linia, rozmiar czcionki):

klucz typesGrupaDomyślnie
galaxyGalaktyki#f4b8700.75 · 1 px · solid · 10.5 px
openGromady otwarte#86d3f30.75 · 1 px · solid · 10.5 px
globularGromady kuliste#f3dc8e0.78 · 1 px · solid · 10.5 px
emissionMgławice emisyjne#d4a5ff0.78 · 1 px · solid · 10.5 px
reflectionMgławice refleksyjne#9cc3ff0.75 · 1 px · solid · 10.5 px
planetaryMgławice planetarne#7ee8c60.78 · 1 px · solid · 10.5 px
snrPozostałości po supernowych#ff9eb40.75 · 1 px · solid · 10.5 px
darkCiemne mgławice#b5c0d40.45 · 1 px · solid · 10.5 px
starGwiazdy#fde9b00.7 · 0.9 px · solid · 10 px
solarUkład Słoneczny#e4f68e0.85 · 1.2 px · solid · 12 px
otherInne#dce3f00.65 · 1 px · solid · 10.5 px
klucz catalogsGrupaDomyślnie
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 ciemne (LDN)#93a1b80.45 · 1 px · solid · 10.5 px
lbnLynds jasne (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
clustersGromady gwiazd (Collinder, Melotte, Trumpler, …)#a5e4f70.72 · 1 px · solid · 10.5 px
pnMgławice planetarne (PN G, PK, Abell)#7ee8c60.78 · 1 px · solid · 10.5 px
snrPozostałości po supernowych (SNR G)#ff9eb40.75 · 1 px · solid · 10.5 px
groupsGrupy galaktyk (Arp, Hickson, Abell/ACO)#f4c48a0.7 · 1 px · solid · 10.5 px
rcwWięcej mgławic (RCW, Gum, Cederblad, DWB)#e0b3ff0.72 · 1 px · solid · 10.5 px
starsGwiazdy (nazwy, Bayer, Flamsteed, HR, HD)#fde9b00.7 · 0.9 px · solid · 10 px
customTwoje katalogi (pliki)#ffb86b0.85 · 1 px · solid · 11 px
vizierOnline (VizieR)#9fe8700.7 · 0.9 px · solid · 9.5 px
solarUkład Słoneczny#e4f68e0.85 · 1.2 px · solid · 12 px
otherInne#dce3f00.65 · 1 px · solid · 10.5 px

Błędy

Każda odpowiedź z błędem ma ten sam kształt: kod, na który można zareagować, i komunikat do pokazania. Nieprawidłowe zapytania wymieniają każdy problem:

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" }
  ]
}
StatuserrorKiedy
400invalid_imageObraz nie jest poprawnym base64 albo nie da się go odczytać.
400unsupported_formatPlik nie jest w żadnym z powyższych formatów.
413payload_too_largeTreść zapytania, plik albo liczba jego pikseli przekracza limit.
422invalid_requestBrakuje pola albo jest złego typu, poza zakresem lub nieznane; details wymienia każde.
429rate_limitedTwój adres klienta wyczerpał swoje zapytania; retry_after mówi, kiedy spróbować ponownie.
429busySerwer rozwiązuje tyle, ile może; ponów po Retry-After.
500internal_errorCoś zawiodło po naszej stronie.
503unavailableSolver, solver Księżyca albo moduł adnotacji nie jest gotowy.

Obraz, którego nie da się rozwiązać, nie jest błędem: odpowiedź to 200 z solved: false.

Stan usługi

GET/api/v1/health60 naraz · 60 na minutę

Stan usługi, wczytane indeksy gwiazd, solver Księżyca i workery adnotacji oraz obowiązujące limity.

odpowiedź
{
  "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
  }
}

API zgodne z Astrometry.net

Programy, które rozwiązują astrometrycznie online przez astrometry.net (nova.astrometry.net), mogą zamiast niego używać SkySolver: ustaw w nich serwer na https://skysolver.app. Działa dowolny klucz API, pusty też; nie ma kont. Ścieżki, odpowiedzi i pliki są takie jak w nova, aż po szczegóły, na których polegają jego klienty, w korzeniu strony (/api/…, /wcs_file/…).

ProgramUstawienie
N.I.N.A.Options → Plate solving → Astrometry.net: URL https://skysolver.app, dowolny klucz API
KStars / EkosAlign → solver options → Online (astrometry.net): API URL https://skysolver.app (https: StellarSolver i tak je dodaje), dowolny klucz
astroqueryAstrometryNet() z URL = "https://skysolver.app", API_URL = "https://skysolver.app/api", dowolny api_key
client.py (astrometry.net)--server https://skysolver.app/api/ --apikey anything; używa go skrypt online CCDciel
AstroImageJPlate solve → custom server https://skysolver.app, klucz pusty
SGPsolver ANSVR, Server URL https://skysolver.app/api (ścieżki wywoływane przez SGP są dostępne; nie sprawdzano z samym SGP)
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)
ŚcieżkaCo robi tutaj
POST /api/loginSesja dla dowolnego klucza.
POST /api/uploadObraz (JPEG, PNG, TIFF, FITS, XISF, BMP, GIF, WebP), lista x,y (tabela FITS z X i Y albo tekst z jednym x y na linię) lub listy x i y w request-json. Do 96 MB.
POST /api/url_uploadTylko listy x i y (tak, jak wysyła je astroquery): URL nie jest pobierany.
/api/submissions/IDZgłoszenie i jego zadanie: zadanie jest dostępne od pierwszego odpytania.
/api/jobs/IDprocessing, solving, success lub failure; każde zadanie kończy się jednym z dwóch ostatnich.
/api/jobs/ID/calibration/ra, dec, radius, pixscale, orientation, parity, width_arcsec, height_arcsec, obliczone tak jak w nova.
/api/jobs/ID/info/ · tags/ · machine_tags/ · objects_in_field/ · annotations/Obiekty głębokiego nieba w polu, z pozycjami w pikselach i promieniami w annotations.
/wcs_file/IDRozwiązanie TAN-SIP jako plik FITS z samym nagłówkiem (wcs.fits).
/corr_file/ID · /axy_file/ID · /rdls_file/IDDopasowane gwiazdy, wykryte gwiazdy, dopasowane gwiazdy katalogowe: tabele FITS w kolumnach nova.
/joblog/IDCo zrobiło zadanie, jako tekst.
  • Zawsze w ciemno. Podpowiedzi o skali, pozycji i parzystości są przyjmowane i ignorowane: solver żadnej nie potrzebuje, a błędna podpowiedź nie może zepsuć rozwiązania.
  • Piksele są takie jak w nova: (1, 1) to środek pierwszego zapisanego piksela, lewego górnego w JPEG lub PNG (bez stosowania orientacji EXIF) albo pierwszego wiersza pliku FITS, niezależnie od jego ROWORDER. orientation zachowuje osobliwość nova dla wysłanych JPEG, PNG i GIF, więc programy, które ją odwracają, dostają ten sam kąt co z nova.
  • Panoramy i obrazy całego nieba rozwiązane modelem projekcji mają kalibrację, ale nie mają wcs_file: żaden TAN-SIP ich nie oddaje.
  • Żadne obrazy nie są zachowywane. Wysłany plik jest odrzucany, gdy tylko znalezione zostaną jego gwiazdy, więc new_fits_file oraz obrazy z adnotacjami, czerwono-zielone i z ekstrakcji nie są oferowane. Wyniki zadania są trzymane w pamięci przez 30 minut, a potem zapominane.
  • Limity: wysyłki 20 naraz i 6 na minutę na adres; pozostałe ścieżki liczą się jako lekkie zapytania (60 naraz, 60 na minutę).

Historia zmian

  • 1.2 (19 października 2026): rozwiązywanie Księżyca: /api/v1/solve/moon.
  • 1.1 (17 października 2026): API zgodne z Astrometry.net.
  • 1.0 (16 października 2026): rozwiązywanie obrazu (base64) lub pozycji gwiazd, adnotacje jako SVG lub JSON, ze Słońcem, Księżycem i planetami.

Pytania, błąd, większy limit? [email protected]. Korzystając z API, akceptujesz regulamin; co robi ono z twoimi danymi, opisuje strona prywatności.