L'API SkySolver
Résolvez une photo du ciel nocturne, ou la liste de ses étoiles, et dessinez son annotation, en SVG à poser sur la photo ou en JSON à dessiner vous-même ; ou résolvez une photo de la Lune : les mêmes solveurs et les mêmes annotations que l'atelier. L'API est gratuite et sans clé, et les programmes conçus pour le solveur en ligne d'Astrometry.net, comme N.I.N.A. et KStars, peuvent l'utiliser en changeant une seule adresse : voir comment.
Aperçu
- URL de base
https://skysolver.app/api/v1. Requêtes et réponses sont en JSON (UTF-8) ; l'annotation peut aussi venir en SVG. - Quatre endpoints : résoudre une image envoyée en base64, résoudre des positions d'étoiles que vous avez mesurées vous-même, résoudre une photo de la Lune, et annoter une image résolue.
- CORS est ouvert : vous pouvez appeler l'API depuis une page web.
- Versions : les changements incompatibles reçoivent un nouveau chemin (
/api/v2) ;v1ne gagne que des champs facultatifs. Le document OpenAPI décrit chaque modèle. - Usage raisonnable : le service est gratuit et tourne sur un petit serveur. Pour de gros lots, résolvez des listes d'étoiles que vous détectez vous-même, ou demandez à [email protected].
Démarrage rapide
Résolvez une photo, puis obtenez son annotation en SVG à la taille de la photo, à poser dessus :
# 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.svgLa même chose en JavaScript (Node 18 ou plus récent ; dans un navigateur, seule la lecture du fichier diffère) :
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();
}Et en 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"})Limites
Chaque adresse cliente dispose d'un seau de requêtes par endpoint : jusqu'à la rafale d'un coup, rempli à un rythme constant. Une requête au-delà reçoit aussitôt 429 et Retry-After. Chaque réponse porte RateLimit-Limit (la rafale), RateLimit-Remaining, RateLimit-Reset (secondes jusqu'à ce que le seau soit plein) et RateLimit-Policy.
| Endpoint | Rafale | Remplissage | Corps de requête |
|---|---|---|---|
POST /solve/image | 10 | 1 par minute | 28 MB (un fichier de 20 MB en base64) |
POST /solve/stars | 30 | 30 par minute | 4 MB |
POST /solve/moon | 20 | 10 par minute | 28 MB (un fichier de 20 MB en base64) |
POST /annotate | 30 | 30 par minute | 2 MB |
GET /health | 60 | 60 par minute | – |
- Images : au plus 20 MB et 120 mégapixels. Le solveur cherche pendant au plus
time_limit_ms(1 à 30 s, 12 s par défaut). Une photo de la Lune est résolue à 2048 pixels au plus sur son grand côté (les plus grandes sont réduites d'abord ; la réponse est dans les pixels du fichier) et prend quelques secondes au plus. - Listes d'étoiles : 5 à 10 000 étoiles ; les 3 000 plus brillantes sont utilisées.
- Occupé : le serveur exécute quelques résolutions à la fois (
max_concurrentdans health). Au-delà, une requête reçoit aussitôt429,error: "busy"etRetry-After: attendez ce délai, plus une seconde environ au hasard, et renvoyez-la. GET /healthrenvoie les limites en vigueur.
Conventions
- Les coordonnées célestes sont en degrés dans l'ICRS (J2000) : RA 0–360, Dec −90–90.
- Les pixels se comptent à partir de 0 au centre du pixel en haut à gauche ; x croît vers la droite et y vers le bas. Le coin supérieur gauche de l'image est donc (−0.5, −0.5) et son centre (largeur/2 − 0.5, hauteur/2 − 0.5). FITS compte à partir de 1 : les listes d'étoiles peuvent le dire (
pixel_origin), etfits_headersuit la convention propre à FITS. - Les heures sont en ISO 8601 avec un décalage UTC ou
Z:2024-10-12T21:34:05+02:00. Une heure sans décalage est refusée, jamais devinée. - Les erreurs sont
{"error": code, "message": text}, avecdetailspour les champs invalides : voir Erreurs.
Résoudre une image
Détecte les étoiles d'une image et trouve où elle pointe dans le ciel : à l'aveugle, sans indication de position, d'échelle ni de rotation, pour des champs de quelques minutes d'arc aux panoramas de tout le ciel. L'image est décodée et résolue en mémoire, et n'est pas conservée.
data:image/…;base64, est accepté). Au plus 20 MB décodés et 120 mégapixels. Formats : JPEG, PNG (8/16 bits), TIFF (8/16/32 bits et flottant ; non compressé, LZW, ZIP, PackBits), FITS (entier ou flottant ; gris, RVB ou la mosaïque brute d'une caméra couleur), XISF (non compressé ou zlib), BMP, GIF, TGA et PSD. Les données linéaires (empilements, FITS, XISF) sont étirées avant la détection.12000Autorisé 1000–30000{
"image": "/9j/4AAQSkZJRgABAQEASABIAAD…",
"time_limit_ms": 12000
}La réponse est la solution, plus image (format, width, height) et capture : quand et où la photo a été prise, d'après ses métadonnées (EXIF, XMP, IPTC, en-têtes FITS, propriétés XISF).
+02:00 ; null quand il est inconnu.EXIF DateTimeOriginal, FITS DATE-OBS, XISF Observation:Time:Start…{lat, lon, height, source}, degrés est et nord, mètres.{
"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": []
}
}Résoudre des positions d'étoiles
Résout à partir de positions d'étoiles que vous avez mesurées vous-même (SExtractor, SEP, photutils, le StarDetector de PixInsight, vos propres centroïdes) : l'image ne quitte jamais votre machine, et la requête fait quelques kilo-octets. C'est ainsi que l'atelier résout.
8–1000008–100000[x, y], [x, y, flux] ou {"x": …, "y": …, "flux": …}. flux est n'importe quelle mesure positive de brillance (somme, pic, …) : donnez-le pour chaque étoile ou pour aucune, et sans lui listez les étoiles les plus brillantes d'abord. 30 à 300 étoiles suffisent largement ; les 3 000 plus brillantes sont utilisées. Les positions doivent être dans l'image.5–10000 items0 : le centre du premier pixel est (0, 0), comme dans numpy et OpenCV. 1 : c'est (1, 1), comme dans FITS, SExtractor, astrometry.net et DS9. Les réponses sont toujours en base 0.0Autorisé 0 · 112000Autorisé 1000–30000{
"width": 6000,
"height": 4000,
"stars": [
[3735.37, 69.14, 51230],
[2120.04, 1987.51, 48810],
{ "x": 812.6, "y": 3020.9, "flux": 47002 },
…
]
}La réponse est la solution.
La solution
Les deux endpoints de champ d'étoiles répondent avec cet objet.
200, avec solved: false et une error.{ra, dec} en degrés. null quand le milieu d'une image de tout le ciel n'est pas sur le ciel.top-left, top-right, bottom-right, bottom-left : chacun {name, x, y, ra, dec}, avec ra et dec à null là où un coin est hors du ciel.{width_deg, height_deg} : la longueur angulaire des lignes médianes horizontale et verticale de l'image.normal · mirroredcrval (RA, Dec du pixel de référence), crpix (le pixel de référence, en base 0), cd (degrés par pixel) et sip (polynômes de distorsion, termes [p, q, coefficient]). null pour les solutions par projection.stars (détectées ou fournies), matches, rms_px (l'écart des étoiles appariées au modèle), log_odds (le poids de preuve de l'appariement, un logarithme naturel : une solution exige 25 et 10 étoiles appariées), et les détails de la recherche.[x, y, ra, dec, magnitude] chacune, la magnitude étant le G de Gaia.decode (lecture du fichier), detect, solve, et le total du server pour la requête, en millisecondes.Résoudre une photo de la Lune
Trouve la Lune dans une photo et ajuste son disque : à l'aveugle, à n'importe quelle échelle, rotation et parité, à n'importe quelle phase, que le cadre contienne le disque entier, une partie ou un gros plan de quelques cratères. La photo filtrée passe-bande est appariée, à chaque position, rotation et parité, à un mélange de trois cartes fixes de la face visible (l'albédo et ses deux pentes), ce que n'importe quelle direction du Soleil fait du sol ; la fraction de la photo que le mélange explique est la confiance, et le limbe, quand il y en a un, fixe la libration. La réponse place chaque point de la photo sur la Lune : le centre, le rayon et l'orientation du disque, la libration, et le Soleil et la phase lus d'après le terminateur. Les gros plans se résolvent de façon fiable jusqu'à des régions d'environ 250 km de large ; un champ de moins de 150 km environ, un cratère qui remplit le cadre, revient souvent en unsure. L'image est décodée et résolue en mémoire, et n'est pas conservée.
data:image/…;base64, est accepté). Au plus 20 MB décodés et 120 mégapixels. Formats : JPEG, PNG (8/16 bits), TIFF, WebP, BMP et GIF ; la couleur est convertie en luminance, les données 16 bits étirées par leur pixel le plus brillant. Les pixels sont lus tels que stockés (une orientation EXIF n'est pas appliquée), si bien que la réponse correspond à ce que montre une visionneuse qui l'ignore.{
"image": "/9j/4AAQSkZJRgABAQEASABIAAD…"
}unsure. Une photo sans Lune reste une réponse 200, avec solved: false et une error.verified : une réponse sûre qui a passé les recoupements (un gros plan domine nettement le second candidat de la photo, et s'accorde avec le limbe quand il y en a un dans le cadre). plausible : probable mais non confirmée. unsure : non résolue ; la meilleure hypothèse est tout de même rapportée dans view, pour ce qu'elle vaut.verified · plausible · unsuredisk · closeup · none0–1null quand rien n'a été trouvé : cx, cy, R sont le centre et le rayon du disque en pixels (centres de pixels en base 0 ; pour un gros plan ils sont loin hors du cadre) ; rho est l'angle à l'écran du nord lunaire, en degrés antihoraires depuis le haut de l'image ; par vaut 1 pour une vue directe et -1 pour une vue en miroir ; lon0, lat0 sont le point sub-observateur en degrés sélénographiques (longitude positive vers l'est), c'est-à-dire la libration.{lon, lat, score, terminator}, lu d'après la photo : là où sol éclairé et sol sombre se rencontrent dans le cadre, la longitude du Soleil qui prédit le mieux lequel est lequel (lat vaut 0 ; la vraie valeur est toujours à moins de 1,6°) ; score est la fraction des échantillons du cadre qu'elle prédit correctement. Un disque entier sans terminateur est une pleine lune (terminator: false, le Soleil au point sub-observateur). null pour un gros plan sans terminateur : la phase ne peut pas en être déduite.view et sun : angle_deg (l'angle de phase : 0 pleine, 180 nouvelle), fraction (éclairée), waxing, colongitude (la colongitude sélénographique du Soleil : 0 au premier quartier, 90 à la pleine lune, 180 au dernier quartier) et name (new moon, waxing crescent, first quarter, waxing gibbous, full moon, waning gibbous, last quarter, waning crescent). null sans sun.{cx, cy, R, arc, refined, locked} (pixels comme dans view ; arc est la part du cercle qui a été mesurée), null quand aucun limbe n'a été trouvé. locked: true signifie que le cercle de la vue est ce bord ; sinon la texture de surface a placé la sphère elle-même, qui se trouve à l'intérieur du bord débordant d'une Lune surexposée.center et corners (top-left, top-right, bottom-right, bottom-left), chacun {lon, lat} ou null là où le point est hors du disque (les coins d'une photo du disque entier).hyps (positions essayées par la recherche de gros plan) et octaves (octaves d'échelle explorées) ; tous deux à 0 quand le limbe a tranché.decode, limb, disk, closeup, solve et le total du server, en millisecondes.format (tel que le décodeur le nomme : JPEG, PNG, …), width, height.{
"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 }
}Pour dessiner sur la photo, projetez un point sélénographique (lon, lat) avec la vue : avec p = (cos lat cos lon, cos lat sin lon, sin lat), e_z le même vecteur pour (lon0, lat0), e_y l'axe de la Lune rendu perpendiculaire à e_z et 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 ρ) ; le point est sur la face visible quand p·e_z > 0.
Annoter une image résolue
Dessine la grille de coordonnées, les constellations, les objets du ciel profond (20 000 : Messier, NGC, IC, Sharpless, Barnard, Lynds, van den Bergh, Caldwell, les catalogues d'amas d'étoiles, nébuleuses planétaires, rémanents de supernova, groupes de galaxies Arp, Hickson et Abell, RCW et Cederblad), les étoiles nommées et désignées et, avec une heure, le Soleil, la Lune, les planètes, astéroïdes et comètes, comme l'Enregistrer l'image de l'atelier les dessine : les mêmes objets, étiquettes et styles. Vous envoyez le modèle de ciel, pas l'image. L'annotation n'est pas découpée au ciel : l'atelier trouve l'horizon dans la photo lui-même.
corners, wcs et projection ; prise de solution ou des NAXIS1/NAXIS2 de l'en-tête FITS sinon.8–100000svg : un document SVG à la taille de l'image, transparent, à poser sur la photo. json : les objets, corps, lignes et étiquettes placées en données (Sortie JSON)."svg"Autorisé svg · jsonZ). Avec elle, le Soleil, la Lune, les planètes et Pluton sont dessinés là où ils étaient (à 1″ près pour 1850–2150), ainsi que les astéroïdes les plus brillants et les comètes (à environ 1″ près pour 1990–2041).-90–90-180–180-500–100001400Autorisé 200–80000Autorisé 0–1{
"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" } }
}Avec format: "svg" la réponse est en image/svg+xml : <svg width="2048" height="1366" viewBox="0 0 2048 1366">…, dans les pixels de la photo. Un avertissement sur le modèle de ciel, s'il y en a un, vient dans l'en-tête SkySolver-Warning.
Modèles de ciel
Envoyez celui que vous avez ; tous décrivent comment les pixels de l'image se projettent sur le ciel.
{ra, dec} : center, top_left, top_right, bottom_right, bottom_left. Une projection gnomonique (TAN) leur est ajustée ; pour les objectifs grand-angle qui distordent, la réponse avertit de l'écart des coins. Chaque coin doit être à moins de 87° du centre : les vues plus larges exigent la projection du solveur.crval [RA, Dec], crpix [x, y] (en base 0), cd [[CD1_1, CD1_2], [CD2_1, CD2_2]] en degrés par pixel, et en option sip {order, a, b, inv_order, ap, bp} avec des termes [p, q, coefficient].CTYPE1 = 'RA---TAN' ou 'RA---TAN-SIP', CRVAL, CRPIX (en base 1, comme FITS), et CD, ou PC avec CDELT, ou CDELT avec CROTA2 ; les A_*, B_*, AP_*, BP_* de SIP. Ce qu'écrivent astrometry.net, ASTAP, PixInsight et ce solveur./solve le renvoie./solve entière : sa taille et son wcs ou sa projection sont utilisés.Sortie JSON
Avec format: "json" : ce que l'annotation dessine, en pixels de l'image (base 0, y vers le bas), et les étiquettes telles que placées.
center {ra, dec}, scale_arcsec (au centre), diagonal_deg (null pour les vues de tout le ciel).width (la layout_width utilisée) et scale : pixels de l'image par pixel de composition, par lequel tailles et épaisseurs ont été multipliées.M 42, NGC 1977), telle que edits la prend, et l'étiquette dessinée (M42).Orion Nebula, ou celui donné dans edits) et celui du catalogue.emission…) et chaque groupe de catalogue dont il fait partie.["Mel 22", "LBN 770"].[x0, y0, x1, y1, …] en pixels (un contour tracé, ou l'ellipse du catalogue) ; closed est false quand la forme sort du domaine d'une vue de tout le ciel et que seuls des morceaux en sont dessinés.edits.hidden le masque.time : le Soleil, la Lune, les planètes, astéroïdes et comètes dans le cadre : id, name, kind (star, moon, planet, dwarf planet, asteroid, comet), ra, dec, mag (pour une comète, une prévision grossière), diameter_arcsec (null pour les astéroïdes et comètes), distance_au, phase (fraction éclairée), elongation_deg, topocentric (placé comme vu depuis location), uncertainty_arcsec (astéroïdes et comètes : de combien la position peut être décalée), x, y, radius_px, outline, shown.id, name, lines (polylignes en pixels), stars, label_at.kind (ra ou dec), value (degrés), label, lines.kind (ecliptic, galactic, borders), lines, label_at.text, of (l'objet), kind, x, y (l'ancre de la ligne de base du texte), size, anchor (start, middle, end), color, opacity.Options
Toutes facultatives, et partielles : ce que vous omettez garde les valeurs par défaut de l'atelier. Les valeurs hors plage, et les clés qui n'existent pas, sont refusées avec 422 plutôt qu'ignorées.
types ou catalogs ci-dessous s'appliquent alors."type"Autorisé type · catalogon et un style de trait (par défaut #96beff, en tirets).on et un style de trait.on (désactivé par défaut) et un style de trait.on (désactivé par défaut) et un style de trait.on (désactivée par défaut), color, opacity, blur (0–16 px), distance (0–12 px).truetrue{"emission": {"color": "#ff99cc"}}.#rrggbb0–10.3–6solid · dashed · dotted · dashdot6–32group_by: "type") : {"dark": false}. Tous sont activés par défaut.group_by: "catalog").auto : les objets Messier toujours, les autres selon leur importance dans le cadre (taille, ou une limite de magnitude qui suit l'échelle de l'image). Une plage : les objets dont la magnitude est dedans ; ceux qui n'en ont pas (la plupart des nébuleuses) selon leur taille."auto"Autorisé "auto" · [brightest, faintest] within -2–18objects[].id la donne : ["NGC 1999", "Mars"].{"NGC 1499": "California"} ; une chaîne vide étiquette un objet par sa seule désignation.Groupes et styles
Les clés de view.types, filter.types, view.catalogs et filter.catalogs, avec leur style par défaut (couleur, opacité, épaisseur, trait, taille de police) :
| clé types | Groupe | Par défaut |
|---|---|---|
galaxy | Galaxies | #f4b8700.75 · 1 px · solid · 10.5 px |
open | Amas ouverts | #86d3f30.75 · 1 px · solid · 10.5 px |
globular | Amas globulaires | #f3dc8e0.78 · 1 px · solid · 10.5 px |
emission | Nébuleuses en émission | #d4a5ff0.78 · 1 px · solid · 10.5 px |
reflection | Nébuleuses par réflexion | #9cc3ff0.75 · 1 px · solid · 10.5 px |
planetary | Nébuleuses planétaires | #7ee8c60.78 · 1 px · solid · 10.5 px |
snr | Rémanents de supernova | #ff9eb40.75 · 1 px · solid · 10.5 px |
dark | Nébuleuses obscures | #b5c0d40.45 · 1 px · solid · 10.5 px |
star | Étoiles | #fde9b00.7 · 0.9 px · solid · 10 px |
solar | Système solaire | #e4f68e0.85 · 1.2 px · solid · 12 px |
other | Autres | #dce3f00.65 · 1 px · solid · 10.5 px |
| clé catalogs | Groupe | Par défaut |
|---|---|---|
messier | Messier | #f7cf4a0.85 · 1 px · solid · 12 px |
ngc | NGC | #86d3f30.75 · 1 px · solid · 10.5 px |
ic | IC | #aab8ff0.75 · 1 px · solid · 10.5 px |
sharpless | Sharpless (Sh2) | #d4a5ff0.78 · 1 px · solid · 10.5 px |
barnard | Barnard (B) | #b5c0d40.5 · 1 px · solid · 10.5 px |
ldn | Lynds obscures (LDN) | #93a1b80.45 · 1 px · solid · 10.5 px |
lbn | Lynds brillantes (LBN) | #f7a8d30.72 · 1 px · solid · 10.5 px |
vdb | van den Bergh (vdB, vdBH) | #9cc3ff0.75 · 1 px · solid · 10.5 px |
caldwell | Caldwell | #7ee8c60.75 · 1 px · solid · 10.5 px |
clusters | Amas d'étoiles (Collinder, Melotte, Trumpler, …) | #a5e4f70.72 · 1 px · solid · 10.5 px |
pn | Nébuleuses planétaires (PN G, PK, Abell) | #7ee8c60.78 · 1 px · solid · 10.5 px |
snr | Rémanents de supernova (SNR G) | #ff9eb40.75 · 1 px · solid · 10.5 px |
groups | Groupes de galaxies (Arp, Hickson, Abell/ACO) | #f4c48a0.7 · 1 px · solid · 10.5 px |
rcw | Autres nébuleuses (RCW, Gum, Cederblad, DWB) | #e0b3ff0.72 · 1 px · solid · 10.5 px |
stars | Étoiles (noms, Bayer, Flamsteed, HR, HD) | #fde9b00.7 · 0.9 px · solid · 10 px |
custom | Vos catalogues (fichiers) | #ffb86b0.85 · 1 px · solid · 11 px |
vizier | En ligne (VizieR) | #9fe8700.7 · 0.9 px · solid · 9.5 px |
solar | Système solaire | #e4f68e0.85 · 1.2 px · solid · 12 px |
other | Autres | #dce3f00.65 · 1 px · solid · 10.5 px |
Erreurs
Chaque réponse d'erreur a la même forme : un code sur lequel agir, et un message à afficher. Les requêtes invalides listent chaque problème :
{
"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" }
]
}| Statut | error | Quand |
|---|---|---|
| 400 | invalid_image | L'image n'est pas du base64 valide, ou ne peut pas être lue. |
| 400 | unsupported_format | Le fichier n'est pas dans l'un des formats ci-dessus. |
| 413 | payload_too_large | Le corps de la requête, le fichier ou son nombre de pixels dépasse la limite. |
| 422 | invalid_request | Un champ manque, est du mauvais type, hors plage ou inconnu ; details les liste un à un. |
| 429 | rate_limited | Votre adresse cliente a épuisé ses requêtes ; retry_after dit quand réessayer. |
| 429 | busy | Le serveur résout autant qu'il peut ; réessayez après Retry-After. |
| 500 | internal_error | Quelque chose a échoué de notre côté. |
| 503 | unavailable | Le solveur, le solveur lunaire ou l'annotateur n'est pas prêt. |
Une image qui ne peut pas être résolue n'est pas une erreur : la réponse est 200 avec solved: false.
État du service
L'état du service, les index d'étoiles, le solveur lunaire et les workers d'annotation chargés, et les limites en vigueur.
{
"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 compatible Astrometry.net
Les programmes qui résolvent en ligne avec astrometry.net (nova.astrometry.net) peuvent utiliser SkySolver à la place : réglez leur serveur sur https://skysolver.app. N'importe quelle clé d'API fonctionne, une clé vide aussi ; il n'y a pas de comptes. Les routes, les réponses et les fichiers sont ceux de nova, jusqu'aux détails sur lesquels ses clients comptent, à la racine du site (/api/…, /wcs_file/…).
| Programme | Réglage |
|---|---|
| N.I.N.A. | Options → Plate solving → Astrometry.net : URL https://skysolver.app, n'importe quelle clé d'API |
| KStars / Ekos | Align → solver options → Online (astrometry.net) : API URL https://skysolver.app (https : StellarSolver l'ajoute de toute façon), n'importe quelle clé |
| astroquery | AstrometryNet() avec URL = "https://skysolver.app", API_URL = "https://skysolver.app/api", n'importe quel api_key |
| client.py (astrometry.net) | --server https://skysolver.app/api/ --apikey anything ; le script en ligne de CCDciel l'utilise |
| AstroImageJ | Plate solve → custom server https://skysolver.app, clé vide |
| SGP | le solveur ANSVR, Server URL https://skysolver.app/api (les routes que SGP appelle y sont ; non essayé avec SGP lui-même) |
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)| Route | Ce qu'elle fait ici |
|---|---|
POST /api/login | Une session pour n'importe quelle clé. |
POST /api/upload | Une image (JPEG, PNG, TIFF, FITS, XISF, BMP, GIF, WebP), une liste x,y (une table FITS avec X et Y, ou du texte avec un x y par ligne), ou des listes x et y dans request-json. Jusqu'à 96 MB. |
POST /api/url_upload | Listes x et y seulement (comme astroquery les envoie) : aucune URL n'est téléchargée. |
/api/submissions/ID | La soumission et son job : le job est là dès la première interrogation. |
/api/jobs/ID | processing, solving, success ou failure ; chaque job finit dans l'un des deux derniers. |
/api/jobs/ID/calibration/ | ra, dec, radius, pixscale, orientation, parity, width_arcsec, height_arcsec, calculés comme nova le fait. |
/api/jobs/ID/info/ · tags/ · machine_tags/ · objects_in_field/ · annotations/ | Les objets du ciel profond dans le champ, avec leurs positions et rayons en pixels dans annotations. |
/wcs_file/ID | La solution TAN-SIP en fichier FITS d'en-tête seul (wcs.fits). |
/corr_file/ID · /axy_file/ID · /rdls_file/ID | Les étoiles appariées, les étoiles détectées, les étoiles du catalogue appariées : des tables FITS dans les colonnes de nova. |
/joblog/ID | Ce que le job a fait, en texte. |
- Toujours à l'aveugle. Les indications d'échelle, de position et de parité sont acceptées et ignorées : le solveur n'en a pas besoin, et une indication fausse ne peut pas gâcher une résolution.
- Les pixels sont ceux de nova :
(1, 1)est le centre du premier pixel stocké, le coin supérieur gauche d'un JPEG ou PNG (son orientation EXIF non appliquée) ou la première ligne d'un fichier FITS, quel que soit sonROWORDER. L'orientationgarde la particularité de nova pour les envois JPEG, PNG et GIF, si bien que les programmes qui la retournent obtiennent le même angle qu'avec nova. - Les panoramas et images de tout le ciel résolus avec un modèle de projection ont une calibration mais pas de
wcs_file: aucun TAN-SIP ne les contient. - Aucune image n'est conservée. Un envoi est abandonné dès que ses étoiles sont trouvées, si bien que
new_fits_fileet les images annotée, rouge-verte et d'extraction ne sont pas proposées. Les résultats d'un job sont gardés en mémoire 30 minutes, puis oubliés. - Limites : envois 20 d'un coup et 6 par minute par adresse ; les autres routes comptent comme requêtes légères (60 d'un coup, 60 par minute).
Journal des modifications
- 1.2 (19 octobre 2026) : résolution de la Lune :
/api/v1/solve/moon. - 1.1 (17 octobre 2026) : l'API compatible Astrometry.net.
- 1.0 (16 octobre 2026) : résoudre une image (base64) ou des positions d'étoiles, annoter en SVG ou JSON, avec le Soleil, la Lune et les planètes.
Des questions, un bug, un quota plus large ? [email protected]. En utilisant l'API vous acceptez les conditions d'utilisation ; ce qu'elle fait de vos données est dans la page confidentialité.