API · v1

La API de SkySolver

Resuelve la astrometría de una foto del cielo nocturno, o de una lista de sus estrellas, y dibuja su anotación, como SVG para superponer a la foto o como JSON para dibujarla tú mismo; o resuelve una foto de la Luna: los mismos solucionadores y las mismas anotaciones que el taller. Es gratuita y no necesita clave, y los programas hechos para el solucionador en línea de Astrometry.net, como N.I.N.A. y KStars, pueden usarla cambiando una sola dirección: mira cómo.

Resumen

Sin clave
Gratis y anónima: sin cuenta ni clave de API.
Con límite de peticiones
Por dirección de cliente, según lo pesado que sea el endpoint.
No se conserva nada
Las imágenes, las listas de estrellas y los resultados no se almacenan ni se registran.
  • URL base https://skysolver.app/api/v1. Las peticiones y las respuestas son JSON (UTF-8); la anotación también puede venir como SVG.
  • Cuatro endpoints: resolver una imagen enviada en base64, resolver posiciones de estrellas que hayas medido tú mismo, resolver una foto de la Luna y anotar una imagen resuelta.
  • CORS está abierto: puedes llamar a la API desde una página web.
  • Versiones: los cambios incompatibles reciben una ruta nueva (/api/v2); v1 solo gana campos opcionales. El documento OpenAPI describe todos los modelos.
  • Uso razonable: el servicio es gratuito y corre en un servidor pequeño. Para lotes grandes, resuelve listas de estrellas que detectes tú mismo, o pregunta en [email protected].

Inicio rápido

Resuelve una foto y luego obtén su anotación como un SVG del tamaño de la foto, para superponerlo:

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

Lo mismo en JavaScript (Node 18 o posterior; en un navegador solo cambia la lectura del archivo):

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

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

Límites

Cada dirección de cliente tiene un cubo de peticiones por endpoint: hasta burst de golpe, recargado a un ritmo constante. Una petición más allá se responde al instante con 429 y Retry-After. Cada respuesta lleva RateLimit-Limit (la ráfaga), RateLimit-Remaining, RateLimit-Reset (segundos hasta que el cubo esté lleno) y RateLimit-Policy.

EndpointRáfagaRecargaCuerpo de la petición
POST /solve/image101 por minuto28 MB (un archivo de 20 MB en base64)
POST /solve/stars3030 por minuto4 MB
POST /solve/moon2010 por minuto28 MB (un archivo de 20 MB en base64)
POST /annotate3030 por minuto2 MB
GET /health6060 por minuto–
  • Imágenes: como máximo 20 MB y 120 megapíxeles. El solucionador busca durante como máximo time_limit_ms (1–30 s, 12 s por defecto). Una foto de la Luna se resuelve a un máximo de 2048 píxeles en su lado largo (las mayores se reducen antes; la respuesta está en los píxeles del archivo) y tarda unos pocos segundos como mucho.
  • Listas de estrellas: de 5 a 10 000 estrellas; se usan las 3000 más brillantes.
  • Ocupado: el servidor ejecuta unas pocas soluciones a la vez (max_concurrent en health). Más allá, una petición se responde al instante con 429, error: "busy" y Retry-After: espera ese tiempo, más un segundo aleatorio más o menos, y vuelve a enviarla.
  • GET /health devuelve los límites en vigor.

Convenciones

  • Las coordenadas celestes son grados en el ICRS (J2000): RA 0–360, Dec −90–90.
  • Los píxeles se cuentan desde 0 en el centro del píxel superior izquierdo; x crece hacia la derecha e y hacia abajo. La esquina superior izquierda de la imagen es por tanto (−0,5, −0,5) y su centro (ancho/2 − 0,5, alto/2 − 0,5). FITS cuenta desde 1: las listas de estrellas pueden indicarlo (pixel_origin), y fits_header usa la convención propia de FITS.
  • Las horas son ISO 8601 con desfase UTC o Z: 2024-10-12T21:34:05+02:00. Una hora sin él se rechaza, nunca se adivina.
  • Los errores son {"error": código, "message": texto}, con details para los campos no válidos: consulta Errores.

Resolver una imagen

POST/api/v1/solve/image10 de golpe · 1 por minuto

Detecta las estrellas de una imagen y averigua hacia dónde apunta en el cielo: a ciegas, sin ninguna pista de posición, escala ni rotación, para campos desde unos pocos minutos de arco hasta panoramas de todo el cielo. La imagen se decodifica y se resuelve en memoria y no se conserva.

Parámetros
image
stringobligatorio
El archivo de imagen, codificado en base64 (alfabeto estándar o URL-safe; un prefijo data:image/…;base64, no molesta). Como máximo 20 MB decodificados y 120 megapíxeles. Formatos: JPEG, PNG (8/16 bits), TIFF (8/16/32 bits y coma flotante; sin comprimir, LZW, ZIP, PackBits), FITS (entero o coma flotante; gris, RGB o el mosaico en bruto de una cámara de color), XISF (sin comprimir o zlib), BMP, GIF, TGA y PSD. Los datos lineales (apilados, FITS, XISF) se estiran antes de la detección.
time_limit_ms
integeropcional
Cuánto tiempo puede buscar el solucionador antes de rendirse.
Predeterminado 12000Permitido 1000–30000
petición
{
  "image": "/9j/4AAQSkZJRgABAQEASABIAAD…",
  "time_limit_ms": 12000
}

La respuesta es la solución, más image (format, width, height) y capture: cuándo y dónde se tomó la foto, según sus metadatos (EXIF, XMP, IPTC, cabeceras FITS, propiedades XISF).

capture
time
object | null
La hora de captura, o null cuando el archivo no la tiene.
└utc
string | null
El instante en UTC: null cuando el archivo da una lectura del reloj sin su zona horaria (EXIF anterior a 2.31, el XMP de Lightroom).
└local
string
La lectura del reloj tal como está escrita: la hora local de la cámara en EXIF, UTC en FITS.
└utc_offset
string | null
El desfase del reloj, +02:00; null cuando se desconoce.
└source
string
De dónde se leyó: EXIF DateTimeOriginal, FITS DATE-OBS, XISF Observation:Time:Start…
└exposure_s
number
La exposición (o, en un apilado, del primer inicio al último final) cuando se conoce; la hora es entonces su punto medio.
└note
string
Algo que comprobar: un apilado fechado por una de sus tomas, una cámara que quizá no tenía la zona horaria puesta.
└date_only
boolean
true cuando el archivo da una fecha sin hora del día.
location
object | null
Dónde se tomó, según el GPS o las palabras clave de sitio de FITS: {lat, lon, height, source}, grados este y norte, metros.
other_dates
array
Otras fechas del archivo que pueden no ser la hora de captura (creación, modificación), con la misma forma que time.
respuesta (abreviada)
{
  "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": []
  }
}

Resolver posiciones de estrellas

POST/api/v1/solve/stars30 de golpe · 30 por minuto

Resuelve a partir de posiciones de estrellas que hayas medido tú mismo (SExtractor, SEP, photutils, el StarDetector de PixInsight, tus propios centroides): la imagen nunca sale de tu equipo, y la petición ocupa unos pocos kilobytes. Así es como resuelve el taller.

Parámetros
width
integerobligatorio
Ancho de la imagen en píxeles.
Permitido 8–100000
height
integerobligatorio
Alto de la imagen en píxeles.
Permitido 8–100000
stars
arrayobligatorio
Posiciones de las estrellas, cada una [x, y], [x, y, flux] o {"x": …, "y": …, "flux": …}. flux es cualquier medida positiva de brillo (suma, pico, …): dalo para todas las estrellas o para ninguna, y sin él lista las estrellas de más a menos brillante. Con 30 a 300 estrellas sobra; se usan las 3000 más brillantes. Las posiciones deben caer dentro de la imagen.
Permitido 5–10000 items
pixel_origin
integeropcional
0: el centro del primer píxel es (0, 0), como en numpy y OpenCV. 1: es (1, 1), como en FITS, SExtractor, astrometry.net y DS9. Las respuestas siempre empiezan en 0.
Predeterminado 0Permitido 0 · 1
time_limit_ms
integeropcional
Cuánto tiempo puede buscar el solucionador.
Predeterminado 12000Permitido 1000–30000
petición
{
  "width": 6000,
  "height": 4000,
  "stars": [
    [3735.37, 69.14, 51230],
    [2120.04, 1987.51, 48810],
    { "x": 812.6, "y": 3020.9, "flux": 47002 },
    …
  ]
}

La respuesta es la solución.

La solución

Los dos endpoints de campos de estrellas responden con este objeto.

campos
solved
boolean
Si se encontró una solución. Una foto que no se puede resolver sigue siendo una respuesta 200, con solved: false y un error.
width, height
integer
El tamaño de la imagen en píxeles.
center
object | null
El cielo en el centro de la imagen: {ra, dec} en grados. null cuando el centro de una imagen de todo el cielo no está sobre el cielo.
corners
array
Las cuatro esquinas exteriores de la imagen, top-left, top-right, bottom-right, bottom-left: cada una {name, x, y, ra, dec}, con ra y dec null donde una esquina queda fuera del cielo.
fov
object
{width_deg, height_deg}: la longitud angular de las líneas medias horizontal y vertical de la imagen.
scale_arcsec
number
Segundos de arco por píxel en el centro.
rotation_deg
number
Hacia dónde apunta el «arriba» de la imagen: grados desde el norte hacia el este (0: el norte arriba, 90: el este arriba).
parity
string
Las imágenes especulares (invertidas al procesar, o a través de una diagonal) también se resuelven.
Permitido normal · mirrored
wcs
object | null
La solución como TAN o TAN-SIP: crval (RA, Dec del píxel de referencia), crpix (el píxel de referencia, desde 0), cd (grados por píxel) y sip (polinomios de distorsión, términos [p, q, coeficiente]). null para soluciones de proyección.
projection
object | null
La solución como modelo de proyección, para panoramas, ojo de pez y vistas de todo el cielo que ningún TAN-SIP ajusta; null en otro caso. Pásalo, o la solución entera, a /annotate.
stats
object
stars (detectadas o dadas), matches, rms_px (a qué distancia del modelo quedan las estrellas emparejadas), log_odds (la evidencia de la coincidencia, un logaritmo natural: una solución necesita 25 y 10 estrellas emparejadas) y detalles de la búsqueda.
fits_header
string | null
La solución TAN-SIP como cabecera WCS de FITS (tarjetas de 80 caracteres; CRPIX desde 1, como en FITS), lista para fusionar en un archivo FITS. null para soluciones de proyección.
matched
array
Las estrellas de catálogo (Gaia DR3) que la solución emparejó, hasta unos pocos miles: [x, y, ra, dec, magnitude] cada una, la magnitud es la G de Gaia.
timing_ms
object
decode (lectura del archivo), detect, solve y el total del server para la petición, en milisegundos.
error
string
Por qué no hay solución (cuando solved es false).
api_version
string
1.0

Resolver una foto de la Luna

POST/api/v1/solve/moon20 de golpe · 10 por minuto

Encuentra la Luna en una foto y ajusta su disco: a ciegas, a cualquier escala, rotación e inversión, en cualquier fase, tanto si el encuadre contiene el disco entero como una parte o un primer plano de unos pocos cráteres. La foto filtrada en banda se compara, en cada posición, rotación y paridad, como una mezcla de tres mapas fijos de la cara visible (el albedo y sus dos pendientes), que es lo que cualquier dirección del Sol hace con el terreno; la fracción de la foto que la mezcla explica es la confianza, y el limbo, cuando lo hay, fija la libración. La respuesta sitúa cada punto de la foto sobre la Luna: el centro, el radio y la orientación del disco, la libración, y el Sol y la fase leídos del terminador. Los primeros planos se resuelven con fiabilidad hasta regiones de unos 250 km de ancho; un campo de menos de unos 150 km, un cráter que llena el encuadre, a menudo vuelve como unsure. La imagen se decodifica y se resuelve en memoria y no se conserva.

Parámetros
image
stringobligatorio
La foto, codificada en base64 (alfabeto estándar o URL-safe; un prefijo data:image/…;base64, no molesta). Como máximo 20 MB decodificados y 120 megapíxeles. Formatos: JPEG, PNG (8/16 bits), TIFF, WebP, BMP y GIF; el color se convierte a luminancia, los datos de 16 bits se estiran por su píxel más brillante. Los píxeles se leen tal como están almacenados (no se aplica la orientación EXIF), así que la respuesta coincide con lo que muestra un visor de imágenes que la ignore.
petición
{
  "image": "/9j/4AAQSkZJRgABAQEASABIAAD…"
}
campos
solved
boolean
Si se encontró la Luna con un veredicto distinto de unsure. Una foto sin Luna sigue siendo una respuesta 200, con solved: false y un error.
verdict
string
verified: una respuesta segura que superó las comprobaciones cruzadas (un primer plano destaca claramente sobre la segunda opción de la propia foto, y concuerda con el limbo cuando hay uno en el encuadre). plausible: probable pero no confirmada. unsure: sin resolver; la mejor conjetura se informa de todos modos en view, por lo que pueda valer.
Permitido verified · plausible · unsure
path
string
Cómo se resolvió: a partir del limbo del disco (la Luna entera, o una gran parte, en el encuadre) o mediante la búsqueda de primer plano sobre la cara visible.
Permitido disk · closeup · none
confidence
number
La fracción de la energía filtrada en banda de la foto que el modelo de iluminación explica en la respuesta.
Permitido 0–1
runner_up
number
La misma medida para la mejor respuesta distinta (otro lugar, rotación, escala o paridad).
width, height
integer
El tamaño de la imagen en píxeles. Todos los valores en píxeles de abajo están en este marco.
view
object | null
El disco en la foto, null cuando no se encontró nada: cx, cy, R son el centro y el radio del disco en píxeles (centros de píxel desde 0; en un primer plano quedan muy fuera del encuadre); rho es el ángulo en pantalla del norte lunar, grados en sentido antihorario desde el «arriba» de la imagen; par es 1 para una vista directa y -1 para una especular; lon0, lat0 son el punto subobservador en grados selenográficos (longitud positiva hacia el este), es decir, la libración.
scale_km_px
number
Kilómetros por píxel en el centro del disco: 1737,4 km dividido por R.
sun
object | null
El punto subsolar, {lon, lat, score, terminator}, leído de la foto: donde se encuentran el terreno iluminado y el oscuro en el encuadre, la longitud del Sol que mejor predice cuál es cuál (lat es 0; el valor real siempre está a menos de 1,6°); score es la fracción de las muestras del encuadre que predice bien. Un disco entero sin terminador es una Luna llena (terminator: false, el Sol en el punto subobservador). null para un primer plano sin terminador: la fase no se puede deducir de él.
phase
object | null
A partir de view y sun: angle_deg (el ángulo de fase: 0 llena, 180 nueva), fraction (iluminada), waxing, colongitude (la colongitud selenográfica del Sol: 0 en cuarto creciente, 90 llena, 180 en cuarto menguante) y name (new moon, waxing crescent, first quarter, waxing gibbous, full moon, waning gibbous, last quarter, waning crescent). null sin sun.
limb
object | null
El borde brillante del disco tal como se midió en la foto, {cx, cy, R, arc, refined, locked} (píxeles como en view; arc es la parte del círculo que se midió), null cuando no se encontró limbo. locked: true significa que el círculo de la vista es este borde; en otro caso, la textura de la superficie situó la esfera por sí misma, que queda dentro del borde rebosado de una Luna sobreexpuesta.
frame
object | null
Las coordenadas selenográficas bajo el encuadre: center y corners (top-left, top-right, bottom-right, bottom-left), cada una {lon, lat} o null donde el punto queda fuera del disco (las esquinas de una foto del disco entero).
stats
object
hyps (posiciones probadas por la búsqueda de primer plano) y octaves (octavas de escala buscadas); ambos 0 cuando el limbo lo zanjó.
timing_ms
object
decode, limb, disk, closeup, solve y el total del server, en milisegundos.
image
object
format (tal como lo nombra el decodificador: JPEG, PNG, …), width, height.
error
string
Por qué no hay solución (cuando solved es false).
api_version
string
1.0
respuesta (un primer plano de Sinus Iridum al amanecer)
{
  "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 }
}

Para dibujar sobre la foto, proyecta un punto selenográfico (lon, lat) con la vista: con p = (cos lat cos lon, cos lat sin lon, sin lat), e_z el mismo vector para (lon0, lat0), e_y el eje de la Luna hecho perpendicular a e_z y 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 ρ); el punto está en la cara visible cuando p·e_z > 0.

Anotar una imagen resuelta

POST/api/v1/annotate30 de golpe · 30 por minuto

Dibuja la cuadrícula de coordenadas, las constelaciones, los objetos de cielo profundo (20 000: Messier, NGC, IC, Sharpless, Barnard, Lynds, van den Bergh, Caldwell, los catálogos de cúmulos estelares, nebulosas planetarias, restos de supernova, grupos de galaxias de Arp, Hickson y Abell, RCW y Cederblad), las estrellas con nombre y designación y, dada una hora, el Sol, la Luna, los planetas, asteroides y cometas, tal como los dibuja Guardar imagen en el taller: los mismos objetos, etiquetas y estilos. Envías el modelo de cielo, no la imagen. La anotación no se recorta al cielo: el taller encuentra el horizonte en la propia foto.

Parámetros
sky model
one ofobligatorio
Exactamente uno de corners, wcs, fits_header, projection o solution: consulta Modelos de cielo.
width, height
integeropcional
El tamaño de la imagen en píxeles. Obligatorio con corners, wcs y projection; en otro caso se toma de solution o de NAXIS1/NAXIS2 de la cabecera FITS.
Permitido 8–100000
format
stringopcional
svg: un documento SVG del tamaño de la imagen, transparente, para superponer a la foto. json: los objetos, cuerpos, líneas y etiquetas colocadas como datos (Salida JSON).
Predeterminado "svg"Permitido svg · json
time
stringopcional
Cuándo se tomó la foto (ISO 8601 con desfase o Z). Con ella, el Sol, la Luna, los planetas y Plutón se dibujan donde estaban (con 1″ de precisión para 1850–2150), y los asteroides más brillantes y los cometas (con alrededor de 1″ para 1990–2041).
location
objectopcional
Dónde se tomó: la Luna se desplaza hasta un grado con el lugar del observador (su paralaje). Sin ubicación, la Luna se sitúa como se ve desde el centro de la Tierra.
└lat
numberobligatorio
Latitud, grados norte.
Permitido -90–90
└lon
numberobligatorio
Longitud, grados este.
Permitido -180–180
└height
numberopcional
Metros sobre el nivel del mar.
Permitido -500–10000
layout_width
integeropcional
La anotación se compone como para la foto mostrada con este ancho en píxeles, y luego se escala a su tamaño: los grosores de línea y los tamaños de letra son píxeles de esa vista. Mayor: etiquetas más pequeñas y más numerosas.
Predeterminado 1400Permitido 200–8000
detail
numberopcional
Cuánto más mostrar, como al acercar en el taller: 0 la selección predeterminada (objetos destacados), 1 todos los objetos que el filtro deja pasar.
Predeterminado 0Permitido 0–1
view
objectopcional
Capas y estilos: consulta Opciones.
filter
objectopcional
Qué grupos y magnitudes se muestran: consulta Opciones.
edits
objectopcional
Objetos sueltos ocultos o renombrados: consulta Opciones.
petición
{
  "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" } }
}

Con format: "svg" la respuesta es image/svg+xml: <svg width="2048" height="1366" viewBox="0 0 2048 1366">…, en los píxeles de la foto. Un aviso sobre el modelo de cielo, si lo hay, viene en la cabecera SkySolver-Warning.

Modelos de cielo

Envía el que tengas; todos describen cómo los píxeles de la imagen se corresponden con el cielo.

uno de
corners
object
El cielo en el centro de la imagen y en sus cuatro esquinas exteriores, cada uno {ra, dec}: center, top_left, top_right, bottom_right, bottom_left. Se les ajusta una proyección gnomónica (TAN); para objetivos gran angular que distorsionan, la respuesta avisa de a qué distancia quedan las esquinas de ella. Cada esquina debe estar a menos de 87° del centro: las vistas más amplias necesitan la projection del solucionador.
wcs
object
TAN o TAN-SIP tal como lo da el solucionador: crval [RA, Dec], crpix [x, y] (desde 0), cd [[CD1_1, CD1_2], [CD2_1, CD2_2]] en grados por píxel y, opcionalmente, sip {order, a, b, inv_order, ap, bp} con términos [p, q, coeficiente].
fits_header
string
Una cabecera WCS de FITS como texto (tarjetas de 80 caracteres, o una tarjeta por línea): CTYPE1 = 'RA---TAN' o 'RA---TAN-SIP', CRVAL, CRPIX (desde 1, como en FITS), y CD, o PC con CDELT, o CDELT con CROTA2; los A_*, B_*, AP_*, BP_* de SIP. Lo que escriben astrometry.net, ASTAP, PixInsight y este solucionador.
projection
object
El modelo de proyección del solucionador (panoramas, ojo de pez e imágenes de todo el cielo), tal como lo devuelve /solve.
solution
object
Una respuesta entera de /solve: se usan su tamaño y su wcs o projection.

Salida JSON

Con format: "json": lo que dibuja la anotación, en píxeles de la imagen (desde 0, y hacia abajo), y las etiquetas tal como quedan colocadas.

campos
width, height
integer
El tamaño de imagen para el que se dibujó la anotación.
field
object
center {ra, dec}, scale_arcsec (en el centro), diagonal_deg (null para vistas de todo el cielo).
layout
object
width (el layout_width usado) y scale: píxeles de imagen por píxel de composición, por el que se multiplicaron los tamaños y grosores.
objects
array
Los objetos de cielo profundo que seleccionan el filtro y la vista, ocultos incluidos (shown: false).
└id, label
string
Designación (M 42, NGC 1977), tal como la acepta edits, y la etiqueta dibujada (M42).
└name, catalogue_name
string | null
El nombre dibujado (Orion Nebula, o el dado en edits) y el propio del catálogo.
└type, group, catalogs
string, string, array
Tipo legible, su grupo (emission…) y todos los grupos de catálogo a los que pertenece.
└other_designations
array
Sus otras designaciones: ["Mel 22", "LBN 770"].
└ra, dec, mag
number
Posición y magnitud (null cuando se desconoce).
└size_arcmin, position_angle
array, number
[mayor, menor] y el ángulo del norte hacia el este, cuando se conocen.
└x, y, radius_px
number
Dónde está en la imagen, y su radio en píxeles.
└outline, closed
array | null, boolean
Su forma como anillos [x0, y0, x1, y1, …] en píxeles (un contorno trazado, o la elipse del catálogo); closed es false cuando la forma sale del dominio de una vista de todo el cielo y solo se dibujan trozos de ella.
└shown
boolean
false cuando edits.hidden lo oculta.
bodies
array
Con time: el Sol, la Luna, los planetas, asteroides y cometas del encuadre: id, name, kind (star, moon, planet, dwarf planet, asteroid, comet), ra, dec, mag (en un cometa, una previsión aproximada), diameter_arcsec (null para asteroides y cometas), distance_au, phase (fracción iluminada), elongation_deg, topocentric (situado como se ve desde location), uncertainty_arcsec (asteroides y cometas: cuánto puede desviarse la posición), x, y, radius_px, outline, shown.
constellations
array
id, name, lines (polilíneas en píxeles), stars, label_at.
grid
array
Líneas de RA y Dec: kind (ra o dec), value (grados), label, lines.
lines
array
Las líneas de referencia activadas: kind (ecliptic, galactic, borders), lines, label_at.
labels
array
Cada etiqueta tal como quedó colocada, sin pisar a las demás: text, of (el objeto), kind, x, y (el anclaje de la línea base del texto), size, anchor (start, middle, end), color, opacity.
warnings, time, location
array, string, object
Avisos sobre el modelo de cielo; la hora (UTC) y el lugar usados.

Opciones

Todas opcionales, y parciales: lo que omitas conserva los valores predeterminados del taller. Los valores fuera de rango, y las claves que no existen, se rechazan con 422 en lugar de ignorarse.

view
group_by
stringopcional
Los objetos reciben estilo y se filtran por tipo o por catálogo: entonces se aplican types o catalogs de abajo.
Predeterminado "type"Permitido type · catalog
grid
objectopcional
La cuadrícula RA/Dec: on y un estilo de línea (predeterminado #96beff, discontinua).
constellations
objectopcional
Figuras de líneas y nombres: on y un estilo de línea.
borders
objectopcional
Los límites de las constelaciones de la IAU (Delporte 1930, precesados a J2000): on (desactivado por defecto) y un estilo de línea.
ecliptic, galactic
objectopcional
La eclíptica y el ecuador galáctico, con sus nombres: on (desactivado por defecto) y un estilo de línea.
shadow
objectopcional
Una sombra bajo toda la anotación: on (desactivado por defecto), color, opacity, blur (0–16 px), distance (0–12 px).
objects
booleanopcional
Dibujar los objetos (y el Sol, la Luna, los planetas, asteroides y cometas).
Predeterminado true
labels
booleanopcional
Dibujar las etiquetas.
Predeterminado true
types
objectopcional
Un estilo de línea por grupo de tipo, con las claves de Grupos y estilos: {"emission": {"color": "#ff99cc"}}.
catalogs
objectopcional
Un estilo de línea por grupo de catálogo.
un estilo de línea
color
stringopcional
Color de líneas, marcadores y etiquetas.
Permitido #rrggbb
opacity
numberopcional
Opacidad de las líneas y los marcadores; las etiquetas se dibujan algo más opacas.
Permitido 0–1
width
numberopcional
Grosor de línea, en píxeles de la vista de composición (consulta layout_width).
Permitido 0.3–6
dash
stringopcional
Estilo de línea.
Permitido solid · dashed · dotted · dashdot
size
numberopcional
Tamaño de letra de las etiquetas, en píxeles de la vista de composición.
Permitido 6–32
filter
types
objectopcional
Grupos activados o desactivados (con group_by: "type"): {"dark": false}. Todos están activados por defecto.
catalogs
objectopcional
Lo mismo para los catálogos (con group_by: "catalog").
magnitude
string | arrayopcional
auto: los objetos Messier siempre, los demás según lo que destaquen en el encuadre (tamaño, o un límite de magnitud que sigue la escala de la imagen). Un rango: los objetos con una magnitud dentro de él; los que no la tienen (la mayoría de las nebulosas), por tamaño.
Predeterminado "auto"Permitido "auto" · [brightest, faintest] within -2–18
edits
hidden
arrayopcional
Objetos que omitir, por designación tal como la da objects[].id: ["NGC 1999", "Mars"].
names
objectopcional
Nombres con los que etiquetar objetos: {"NGC 1499": "California"}; una cadena vacía etiqueta un objeto solo por su designación.

Grupos y estilos

Las claves de view.types, filter.types, view.catalogs y filter.catalogs, con su estilo predeterminado (color, opacidad, grosor, línea, tamaño de letra):

clave de typesGrupoPredeterminado
galaxyGalaxias#f4b8700.75 · 1 px · solid · 10.5 px
openCúmulos abiertos#86d3f30.75 · 1 px · solid · 10.5 px
globularCúmulos globulares#f3dc8e0.78 · 1 px · solid · 10.5 px
emissionNebulosas de emisión#d4a5ff0.78 · 1 px · solid · 10.5 px
reflectionNebulosas de reflexión#9cc3ff0.75 · 1 px · solid · 10.5 px
planetaryNebulosas planetarias#7ee8c60.78 · 1 px · solid · 10.5 px
snrRestos de supernova#ff9eb40.75 · 1 px · solid · 10.5 px
darkNebulosas oscuras#b5c0d40.45 · 1 px · solid · 10.5 px
starEstrellas#fde9b00.7 · 0.9 px · solid · 10 px
solarSistema solar#e4f68e0.85 · 1.2 px · solid · 12 px
otherOtros#dce3f00.65 · 1 px · solid · 10.5 px
clave de catalogsGrupoPredeterminado
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 oscuras (LDN)#93a1b80.45 · 1 px · solid · 10.5 px
lbnLynds brillantes (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
clustersCúmulos estelares (Collinder, Melotte, Trumpler, …)#a5e4f70.72 · 1 px · solid · 10.5 px
pnNebulosas planetarias (PN G, PK, Abell)#7ee8c60.78 · 1 px · solid · 10.5 px
snrRestos de supernova (SNR G)#ff9eb40.75 · 1 px · solid · 10.5 px
groupsGrupos de galaxias (Arp, Hickson, Abell/ACO)#f4c48a0.7 · 1 px · solid · 10.5 px
rcwMás nebulosas (RCW, Gum, Cederblad, DWB)#e0b3ff0.72 · 1 px · solid · 10.5 px
starsEstrellas (nombres, Bayer, Flamsteed, HR, HD)#fde9b00.7 · 0.9 px · solid · 10 px
customTus catálogos (archivos)#ffb86b0.85 · 1 px · solid · 11 px
vizierEn línea (VizieR)#9fe8700.7 · 0.9 px · solid · 9.5 px
solarSistema solar#e4f68e0.85 · 1.2 px · solid · 12 px
otherOtros#dce3f00.65 · 1 px · solid · 10.5 px

Errores

Toda respuesta de error tiene la misma forma: un código al que reaccionar y un mensaje que mostrar. Las peticiones no válidas enumeran cada problema:

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" }
  ]
}
EstadoerrorCuándo
400invalid_imageLa imagen no es base64 válido, o no se puede leer.
400unsupported_formatEl archivo no es de uno de los formatos de arriba.
413payload_too_largeEl cuerpo de la petición, el archivo o su número de píxeles supera el límite.
422invalid_requestFalta un campo, o es de tipo incorrecto, está fuera de rango o es desconocido; details enumera cada uno.
429rate_limitedTu dirección de cliente agotó sus peticiones; retry_after dice cuándo volver a intentarlo.
429busyEl servidor está resolviendo todo lo que puede; reintenta tras Retry-After.
500internal_errorAlgo falló de nuestro lado.
503unavailableEl solucionador, el solucionador lunar o el anotador no está listo.

Una imagen que no se puede resolver no es un error: la respuesta es 200 con solved: false.

Estado

GET/api/v1/health60 de golpe · 60 por minuto

El estado del servicio, los índices de estrellas, el solucionador lunar y los procesos de anotación cargados, y los límites en vigor.

respuesta
{
  "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 con Astrometry.net

Los programas que resuelven astrometría en línea con astrometry.net (nova.astrometry.net) pueden usar SkySolver en su lugar: pon su servidor en https://skysolver.app. Cualquier clave de API sirve, también una vacía; no hay cuentas. Las rutas, las respuestas y los archivos son los de nova, hasta los detalles de los que dependen sus clientes, en la raíz del sitio (/api/…, /wcs_file/…).

ProgramaAjuste
N.I.N.A.Options → Plate solving → Astrometry.net: URL https://skysolver.app, cualquier clave de API
KStars / EkosAlign → solver options → Online (astrometry.net): API URL https://skysolver.app (https: StellarSolver lo añade de todos modos), cualquier clave
astroqueryAstrometryNet() con URL = "https://skysolver.app", API_URL = "https://skysolver.app/api", cualquier api_key
client.py (astrometry.net)--server https://skysolver.app/api/ --apikey loquesea; el script en línea de CCDciel lo usa
AstroImageJPlate solve → custom server https://skysolver.app, clave vacía
SGPel solucionador ANSVR, Server URL https://skysolver.app/api (las rutas que llama SGP están ahí; no probado con el propio 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)
RutaQué hace aquí
POST /api/loginUna sesión para cualquier clave.
POST /api/uploadUna imagen (JPEG, PNG, TIFF, FITS, XISF, BMP, GIF, WebP), una lista x,y (una tabla FITS con X e Y, o texto con un x y por línea), o listas x e y en request-json. Hasta 96 MB.
POST /api/url_uploadSolo listas x e y (tal como las envía astroquery): no se descarga ninguna URL.
/api/submissions/IDEl envío y su trabajo: el trabajo está ahí desde la primera consulta.
/api/jobs/IDprocessing, solving, success o failure; todo trabajo acaba en uno de los dos últimos.
/api/jobs/ID/calibration/ra, dec, radius, pixscale, orientation, parity, width_arcsec, height_arcsec, calculados como lo hace nova.
/api/jobs/ID/info/ · tags/ · machine_tags/ · objects_in_field/ · annotations/Los objetos de cielo profundo del campo, con sus posiciones y radios en píxeles en annotations.
/wcs_file/IDLa solución TAN-SIP como archivo FITS de solo cabecera (wcs.fits).
/corr_file/ID · /axy_file/ID · /rdls_file/IDLas estrellas emparejadas, las estrellas detectadas, las estrellas de catálogo emparejadas: tablas FITS con las columnas de nova.
/joblog/IDQué hizo el trabajo, como texto.
  • Siempre a ciegas. Las pistas de escala, posición y paridad se aceptan y se ignoran: el solucionador no necesita ninguna, y una pista errónea no puede estropear una solución.
  • Los píxeles son los de nova: (1, 1) es el centro del primer píxel almacenado, el superior izquierdo de un JPEG o PNG (sin aplicar su orientación EXIF) o la primera fila de un archivo FITS, sea cual sea su ROWORDER. La orientation conserva la peculiaridad de nova para subidas JPEG, PNG y GIF, de modo que los programas que la deshacen obtienen el mismo ángulo que de nova.
  • Los panoramas y las imágenes de todo el cielo resueltos con un modelo de proyección tienen calibración pero no wcs_file: ningún TAN-SIP los abarca.
  • No se conserva ninguna imagen. Una subida se descarta en cuanto se encuentran sus estrellas, así que new_fits_file y las imágenes anotada, rojo-verde y de extracción no se ofrecen. Los resultados de un trabajo se guardan en memoria durante 30 minutos y luego se olvidan.
  • Límites: subidas, 20 de golpe y 6 por minuto por dirección; las demás rutas cuentan como peticiones ligeras (60 de golpe, 60 por minuto).

Historial de cambios

  • 1.2 (19 de octubre de 2026): resolución de la Luna: /api/v1/solve/moon.
  • 1.1 (17 de octubre de 2026): la API compatible con Astrometry.net.
  • 1.0 (16 de octubre de 2026): resolver una imagen (base64) o posiciones de estrellas, anotar como SVG o JSON, con el Sol, la Luna y los planetas.

¿Preguntas, un error, una cuota mayor? [email protected]. Al usar la API aceptas los términos; lo que hace con tus datos está en la página de privacidad.