A API do SkySolver
Resolva a astrometria de uma foto do céu noturno, ou de uma lista das suas estrelas, e desenhe a sua anotação, como SVG para sobrepor à foto ou como JSON para desenhar você mesmo; ou resolva uma foto da Lua: os mesmos solvers e as mesmas anotações da oficina. É gratuita e não precisa de chave, e programas feitos para o solver online do Astrometry.net, como N.I.N.A. e KStars, podem usá-la mudando um endereço: veja como.
Visão geral
- URL base
https://skysolver.app/api/v1. Requisições e respostas são JSON (UTF-8); a anotação também pode vir como SVG. - Quatro endpoints: resolver uma imagem enviada em base64, resolver posições de estrelas que você mesmo mediu, resolver uma foto da Lua e anotar uma imagem resolvida.
- CORS está aberto: você pode chamar a API a partir de uma página web.
- Versões: mudanças incompatíveis ganham um novo caminho (
/api/v2); av1só ganha campos opcionais. O documento OpenAPI descreve todos os modelos. - Uso justo: o serviço é gratuito e roda num servidor pequeno. Para grandes lotes, resolva listas de estrelas que você mesmo detecta, ou pergunte em [email protected].
Início rápido
Resolva uma foto, depois obtenha a sua anotação como um SVG do tamanho da foto, para sobrepor a ela:
# 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.svgO mesmo em JavaScript (Node 18 ou posterior; num navegador só a leitura do arquivo é diferente):
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();
}E em 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
Cada endereço de cliente tem um balde de requisições por endpoint: até burst de uma vez, recarregado a um ritmo constante. Uma requisição além disso é respondida de imediato com 429 e Retry-After. Toda resposta traz RateLimit-Limit (o burst), RateLimit-Remaining, RateLimit-Reset (segundos até o balde estar cheio) e RateLimit-Policy.
| Endpoint | Burst | Recarga | Corpo da requisição |
|---|---|---|---|
POST /solve/image | 10 | 1 por minuto | 28 MB (um arquivo de 20 MB em base64) |
POST /solve/stars | 30 | 30 por minuto | 4 MB |
POST /solve/moon | 20 | 10 por minuto | 28 MB (um arquivo de 20 MB em base64) |
POST /annotate | 30 | 30 por minuto | 2 MB |
GET /health | 60 | 60 por minuto | – |
- Imagens: no máximo 20 MB e 120 megapixels. O solver busca durante no máximo
time_limit_ms(1–30 s, 12 s por padrão). Uma foto da Lua é resolvida com até 2048 pixels no lado maior (as maiores são reduzidas antes; a resposta vem nos pixels do arquivo) e leva no máximo alguns segundos. - Listas de estrelas: 5 a 10.000 estrelas; as 3.000 mais brilhantes são usadas.
- Ocupado: o servidor executa algumas resoluções de cada vez (
max_concurrentem estado). Além disso, uma requisição é respondida de imediato com429,error: "busy"eRetry-After: espere esse tempo, mais cerca de um segundo aleatório, e envie-a de novo. GET /healthdevolve os limites em vigor.
Convenções
- Coordenadas celestes são graus no ICRS (J2000): RA 0–360, Dec −90–90.
- Pixels contam a partir de 0 no centro do pixel superior esquerdo; x cresce para a direita e y para baixo. O canto superior esquerdo da imagem é portanto (−0.5, −0.5) e o seu centro (largura/2 − 0.5, altura/2 − 0.5). O FITS conta a partir de 1: as listas de estrelas podem dizê-lo (
pixel_origin), efits_headerusa a convenção do próprio FITS. - Horas são ISO 8601 com deslocamento UTC ou
Z:2024-10-12T21:34:05+02:00. Uma hora sem ele é recusada, nunca adivinhada. - Erros são
{"error": código, "message": texto}, comdetailspara campos inválidos: veja Erros.
Resolver uma imagem
Detecta as estrelas de uma imagem e descobre para onde no céu ela aponta: às cegas, sem nenhuma dica de posição, escala ou rotação, para campos de alguns minutos de arco até panoramas de todo o céu. A imagem é decodificada e resolvida em memória e não é guardada.
data:image/…;base64, é aceito). No máximo 20 MB decodificados e 120 megapixels. Formatos: JPEG, PNG (8/16 bits), TIFF (8/16/32 bits e float; sem compressão, LZW, ZIP, PackBits), FITS (inteiro ou float; cinza, RGB ou o mosaico bruto de uma câmera colorida), XISF (sem compressão ou zlib), BMP, GIF, TGA e PSD. Dados lineares (empilhamentos, FITS, XISF) são esticados antes da detecção.12000Permitido 1000–30000{
"image": "/9j/4AAQSkZJRgABAQEASABIAAD…",
"time_limit_ms": 12000
}A resposta é a solução, mais image (format, width, height) e capture: quando e onde a foto foi tirada, segundo os seus metadados (EXIF, XMP, IPTC, cabeçalhos FITS, propriedades XISF).
+02:00; null quando desconhecido.EXIF DateTimeOriginal, FITS DATE-OBS, XISF Observation:Time:Start…{lat, lon, height, source}, graus leste e norte, metros.{
"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 posições de estrelas
Resolve a partir de posições de estrelas que você mesmo mediu (SExtractor, SEP, photutils, o StarDetector do PixInsight, os seus próprios centroides): a imagem nunca sai da sua máquina, e a requisição tem alguns kilobytes. É assim que a oficina resolve.
8–1000008–100000[x, y], [x, y, flux] ou {"x": …, "y": …, "flux": …}. flux é qualquer medida positiva de brilho (soma, pico, …): dê-a para todas as estrelas ou para nenhuma, e sem ela liste as estrelas da mais brilhante para a mais fraca. 30 a 300 estrelas é bastante; as 3.000 mais brilhantes são usadas. As posições têm de estar dentro da imagem.5–10000 items0: o centro do primeiro pixel é (0, 0), como em numpy e OpenCV. 1: é (1, 1), como em FITS, SExtractor, astrometry.net e DS9. As respostas são sempre baseadas em 0.0Permitido 0 · 112000Permitido 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 },
…
]
}A resposta é a solução.
A solução
Os dois endpoints de campos de estrelas respondem com este objeto.
200, com solved: false e um error.{ra, dec} em graus. null quando o meio de uma imagem de todo o céu não está no céu.top-left, top-right, bottom-right, bottom-left: cada um {name, x, y, ra, dec}, com ra e dec null onde um canto está fora do céu.{width_deg, height_deg}: o comprimento angular das linhas médias horizontal e vertical da imagem.normal · mirroredcrval (RA, Dec do pixel de referência), crpix (o pixel de referência, baseado em 0), cd (graus por pixel) e sip (polinômios de distorção, termos [p, q, coeficiente]). null para soluções de projeção.stars (detectadas ou fornecidas), matches, rms_px (a que distância do modelo estão as estrelas identificadas), log_odds (a evidência da correspondência, um logaritmo natural: uma solução precisa de 25 e de 10 estrelas identificadas), e detalhes da busca.[x, y, ra, dec, magnitude] cada, a magnitude sendo o G do Gaia.decode (leitura do arquivo), detect, solve, e o total do server para a requisição, em milissegundos.Resolver uma foto da Lua
Encontra a Lua numa foto e ajusta o seu disco: às cegas, em qualquer escala, rotação e espelhamento, em qualquer fase, quer o enquadramento contenha o disco inteiro, uma parte dele ou um close-up de algumas crateras. A foto filtrada em banda é comparada, em todas as posições, rotações e paridades, como uma mistura de três mapas fixos da face visível (o albedo e as suas duas inclinações), que é o que qualquer direção do Sol faz do terreno; a fração da foto que a mistura explica é a confiança, e o limbo, quando há um, fixa a libração. A resposta coloca cada ponto da foto sobre a Lua: o centro, o raio e a orientação do disco, a libração, e o Sol e a fase lidos do terminador. Close-ups se resolvem com confiança até regiões de cerca de 250 km de largura; um campo com menos de cerca de 150 km, uma cratera preenchendo o enquadramento, muitas vezes volta como unsure. A imagem é decodificada e resolvida em memória e não é guardada.
data:image/…;base64, é aceito). No máximo 20 MB decodificados e 120 megapixels. Formatos: JPEG, PNG (8/16 bits), TIFF, WebP, BMP e GIF; a cor é convertida em luminância, dados de 16 bits esticados pelo seu pixel mais brilhante. Os pixels são lidos como estão armazenados (uma orientação EXIF não é aplicada), portanto a resposta corresponde ao que mostra um visualizador de imagens que a ignora.{
"image": "/9j/4AAQSkZJRgABAQEASABIAAD…"
}unsure. Uma foto sem Lua ainda é uma resposta 200, com solved: false e um error.verified: uma resposta confiante que passou nas verificações cruzadas (um close-up fica bem acima da segunda melhor resposta da própria foto e concorda com o limbo quando há um no enquadramento). plausible: provável mas não confirmada. unsure: não resolvida; o melhor palpite ainda é informado em view, pelo que vale.verified · plausible · unsuredisk · closeup · none0–1null quando nada foi encontrado: cx, cy, R são o centro e o raio do disco em pixels (centros de pixel baseados em 0; para um close-up ficam bem fora do enquadramento); rho é o ângulo na tela do norte lunar, graus no sentido anti-horário a partir do topo da imagem; par é 1 para uma vista direta e -1 para uma espelhada; lon0, lat0 são o ponto sub-observador em graus selenográficos (longitude positiva para leste), isto é, a libração.{lon, lat, score, terminator}, lido da foto: onde o terreno iluminado encontra o não iluminado no enquadramento, a longitude do Sol que melhor prevê qual é qual (lat é 0; o valor real está sempre dentro de 1,6°); score é a fração das amostras do enquadramento que ela prevê corretamente. Um disco inteiro sem terminador é uma Lua cheia (terminator: false, o Sol no ponto sub-observador). null para um close-up sem terminador: a fase não pode ser deduzida dele.view e sun: angle_deg (o ângulo de fase: 0 cheia, 180 nova), fraction (iluminada), waxing, colongitude (a colongitude selenográfica do Sol: 0 no quarto crescente, 90 na cheia, 180 no quarto minguante) e name (new moon, waxing crescent, first quarter, waxing gibbous, full moon, waning gibbous, last quarter, waning crescent). null sem sun.{cx, cy, R, arc, refined, locked} (pixels como em view; arc é a parte do círculo que foi medida), null quando nenhum limbo foi encontrado. locked: true significa que o círculo da vista é esta borda; caso contrário a textura da superfície posicionou a esfera por si, que fica dentro da borda transbordada de uma Lua superexposta.center e corners (top-left, top-right, bottom-right, bottom-left), cada um {lon, lat} ou null onde o ponto está fora do disco (os cantos de uma foto do disco inteiro).hyps (posições tentadas pela busca de close-up) e octaves (oitavas de escala buscadas); ambos 0 quando o limbo resolveu a questão.decode, limb, disk, closeup, solve e o total do server, em milissegundos.format (como o decodificador o nomeia: 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 }
}Para desenhar sobre a foto, projete um ponto selenográfico (lon, lat) com a vista: com p = (cos lat cos lon, cos lat sin lon, sin lat), e_z o mesmo vetor para (lon0, lat0), e_y o eixo da Lua tornado perpendicular a e_z e 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 ρ); o ponto está no lado visível quando p·e_z > 0.
Anotar uma imagem resolvida
Desenha a grade de coordenadas, as constelações, os objetos de céu profundo (20.000 deles: Messier, NGC, IC, Sharpless, Barnard, Lynds, van den Bergh, Caldwell, os catálogos de aglomerados de estrelas, nebulosas planetárias, remanescentes de supernova, grupos de galáxias Arp, Hickson e Abell, RCW e Cederblad), as estrelas com nome e designação e, dada uma hora, o Sol, a Lua, os planetas, asteroides e cometas, como o Salvar imagem da oficina os desenha: os mesmos objetos, rótulos e estilos. Você envia o modelo de céu, não a imagem. A anotação não é recortada ao céu: a oficina encontra o horizonte na própria foto.
corners, wcs e projection; tirado de solution ou de NAXIS1/NAXIS2 do cabeçalho FITS caso contrário.8–100000svg: um documento SVG do tamanho da imagem, transparente, para sobrepor à foto. json: os objetos, corpos, linhas e rótulos posicionados como dados (Saída JSON)."svg"Permitido svg · jsonZ). Com ela, o Sol, a Lua, os planetas e Plutão são desenhados onde estavam (dentro de 1″ para 1850–2150), e os asteroides mais brilhantes e os cometas (dentro de cerca de 1″ para 1990–2041).-90–90-180–180-500–100001400Permitido 200–80000Permitido 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" } }
}Com format: "svg" a resposta é image/svg+xml: <svg width="2048" height="1366" viewBox="0 0 2048 1366">…, nos pixels da foto. Um aviso sobre o modelo de céu, se houver, vem no cabeçalho SkySolver-Warning.
Modelos de céu
Envie o que você tiver; todos descrevem como os pixels da imagem se mapeiam no céu.
{ra, dec}: center, top_left, top_right, bottom_right, bottom_left. Uma projeção gnomônica (TAN) é ajustada a eles; para lentes grande-angulares que distorcem, a resposta avisa a que distância os cantos ficam dela. Cada canto tem de estar a menos de 87° do centro: vistas mais largas precisam do projection do solver.crval [RA, Dec], crpix [x, y] (baseado em 0), cd [[CD1_1, CD1_2], [CD2_1, CD2_2]] em graus por pixel e, opcionalmente, sip {order, a, b, inv_order, ap, bp} com termos [p, q, coeficiente].CTYPE1 = 'RA---TAN' ou 'RA---TAN-SIP', CRVAL, CRPIX (baseado em 1, como no FITS), e CD, ou PC com CDELT, ou CDELT com CROTA2; A_*, B_*, AP_*, BP_* do SIP. O que astrometry.net, ASTAP, PixInsight e este solver escrevem./solve o devolve./solve: o seu tamanho e o seu wcs ou projection são usados.Saída JSON
Com format: "json": o que a anotação desenha, em pixels da imagem (baseados em 0, y para baixo), e os rótulos como posicionados.
center {ra, dec}, scale_arcsec (no centro), diagonal_deg (null para vistas de todo o céu).width (o layout_width usado) e scale: pixels da imagem por pixel de layout, pelo qual tamanhos e larguras foram multiplicados.M 42, NGC 1977), como edits a aceita, e o rótulo desenhado (M42).Orion Nebula, ou o dado em edits) e o próprio do catálogo.emission…) e todos os grupos de catálogo em que está.["Mel 22", "LBN 770"].[x0, y0, x1, y1, …] em pixels (um contorno traçado, ou a elipse do catálogo); closed é false quando a forma sai do domínio de uma vista de todo o céu e só pedaços dela são desenhados.edits.hidden o oculta.time: o Sol, a Lua, os planetas, asteroides e cometas no enquadramento: id, name, kind (star, moon, planet, dwarf planet, asteroid, comet), ra, dec, mag (para um cometa, uma previsão grosseira), diameter_arcsec (null para asteroides e cometas), distance_au, phase (fração iluminada), elongation_deg, topocentric (posicionado como visto de location), uncertainty_arcsec (asteroides e cometas: quanto a posição pode estar errada), x, y, radius_px, outline, shown.id, name, lines (polilinhas em pixels), stars, label_at.kind (ra ou dec), value (graus), label, lines.kind (ecliptic, galactic, borders), lines, label_at.text, of (o objeto), kind, x, y (a âncora da linha de base do texto), size, anchor (start, middle, end), color, opacity.Opções
Todas opcionais, e parciais: o que você omite mantém os padrões da oficina. Valores fora do intervalo, e chaves que não existem, são recusados com 422 em vez de ignorados.
types ou catalogs abaixo se aplicam então."type"Permitido type · catalogon e um estilo de linha (padrão #96beff, tracejada).on e um estilo de linha.on (desligado por padrão) e um estilo de linha.on (desligado por padrão) e um estilo de linha.on (desligado por padrão), 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}. Todos ligados por padrão.group_by: "catalog").auto: objetos Messier sempre, os outros conforme a sua proeminência no enquadramento (tamanho, ou um limite de magnitude que segue a escala da imagem). Um intervalo: objetos com magnitude dentro dele; os sem magnitude (a maioria das nebulosas) pelo tamanho."auto"Permitido "auto" · [brightest, faintest] within -2–18objects[].id a dá: ["NGC 1999", "Mars"].{"NGC 1499": "California"}; uma string vazia rotula um objeto só pela sua designação.Grupos e estilos
As chaves de view.types, filter.types, view.catalogs e filter.catalogs, com o seu estilo padrão (cor, opacidade, largura, linha, tamanho da fonte):
| chave em types | Grupo | Padrão |
|---|---|---|
galaxy | Galáxias | #f4b8700.75 · 1 px · solid · 10.5 px |
open | Aglomerados abertos | #86d3f30.75 · 1 px · solid · 10.5 px |
globular | Aglomerados globulares | #f3dc8e0.78 · 1 px · solid · 10.5 px |
emission | Nebulosas de emissão | #d4a5ff0.78 · 1 px · solid · 10.5 px |
reflection | Nebulosas de reflexão | #9cc3ff0.75 · 1 px · solid · 10.5 px |
planetary | Nebulosas planetárias | #7ee8c60.78 · 1 px · solid · 10.5 px |
snr | Remanescentes de supernova | #ff9eb40.75 · 1 px · solid · 10.5 px |
dark | Nebulosas escuras | #b5c0d40.45 · 1 px · solid · 10.5 px |
star | Estrelas | #fde9b00.7 · 0.9 px · solid · 10 px |
solar | Sistema solar | #e4f68e0.85 · 1.2 px · solid · 12 px |
other | Outros | #dce3f00.65 · 1 px · solid · 10.5 px |
| chave em catalogs | Grupo | Padrão |
|---|---|---|
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 escuras (LDN) | #93a1b80.45 · 1 px · solid · 10.5 px |
lbn | Lynds brilhantes (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 | Aglomerados de estrelas (Collinder, Melotte, Trumpler, …) | #a5e4f70.72 · 1 px · solid · 10.5 px |
pn | Nebulosas planetárias (PN G, PK, Abell) | #7ee8c60.78 · 1 px · solid · 10.5 px |
snr | Remanescentes de supernova (SNR G) | #ff9eb40.75 · 1 px · solid · 10.5 px |
groups | Grupos de galáxias (Arp, Hickson, Abell/ACO) | #f4c48a0.7 · 1 px · solid · 10.5 px |
rcw | Mais nebulosas (RCW, Gum, Cederblad, DWB) | #e0b3ff0.72 · 1 px · solid · 10.5 px |
stars | Estrelas (nomes, Bayer, Flamsteed, HR, HD) | #fde9b00.7 · 0.9 px · solid · 10 px |
custom | Os seus catálogos (arquivos) | #ffb86b0.85 · 1 px · solid · 11 px |
vizier | Online (VizieR) | #9fe8700.7 · 0.9 px · solid · 9.5 px |
solar | Sistema solar | #e4f68e0.85 · 1.2 px · solid · 12 px |
other | Outros | #dce3f00.65 · 1 px · solid · 10.5 px |
Erros
Toda resposta de erro tem a mesma forma: um código para agir e uma mensagem para mostrar. Requisições inválidas listam cada problema:
{
"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" }
]
}| Status | error | Quando |
|---|---|---|
| 400 | invalid_image | A imagem não é base64 válido, ou não pode ser lida. |
| 400 | unsupported_format | O arquivo não é um dos formatos acima. |
| 413 | payload_too_large | O corpo da requisição, o arquivo ou o seu número de pixels passa do limite. |
| 422 | invalid_request | Um campo está ausente, do tipo errado, fora do intervalo ou é desconhecido; details lista cada um. |
| 429 | rate_limited | O seu endereço de cliente esgotou as suas requisições; retry_after diz quando tentar de novo. |
| 429 | busy | O servidor está resolvendo o máximo que consegue; tente de novo após Retry-After. |
| 500 | internal_error | Algo falhou do nosso lado. |
| 503 | unavailable | O solver, o solver da Lua ou o anotador não está pronto. |
Uma imagem que não pode ser resolvida não é um erro: a resposta é 200 com solved: false.
Estado do serviço
O estado do serviço, os índices de estrelas, o solver da Lua e os workers de anotação carregados, e os limites em vigor.
{
"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 compatível com Astrometry.net
Programas que resolvem a astrometria online com o astrometry.net (nova.astrometry.net) podem usar o SkySolver no lugar dele: configure o servidor deles para https://skysolver.app. Qualquer chave de API funciona, uma vazia também; não há contas. As rotas, as respostas e os arquivos são os do nova, até os detalhes de que os seus clientes dependem, na raiz do site (/api/…, /wcs_file/…).
| Programa | Configuração |
|---|---|
| N.I.N.A. | Options → Plate solving → Astrometry.net: URL https://skysolver.app, qualquer chave de API |
| KStars / Ekos | Align → solver options → Online (astrometry.net): API URL https://skysolver.app (https: o StellarSolver o acrescenta de qualquer forma), qualquer chave |
| astroquery | AstrometryNet() com URL = "https://skysolver.app", API_URL = "https://skysolver.app/api", qualquer api_key |
| client.py (astrometry.net) | --server https://skysolver.app/api/ --apikey anything; o script online do CCDciel o usa |
| AstroImageJ | Plate solve → custom server https://skysolver.app, chave vazia |
| SGP | o solver ANSVR, Server URL https://skysolver.app/api (as rotas que o SGP chama estão lá; não testado com o próprio SGP) |
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)| Rota | O que faz aqui |
|---|---|
POST /api/login | Uma sessão para qualquer chave. |
POST /api/upload | Uma imagem (JPEG, PNG, TIFF, FITS, XISF, BMP, GIF, WebP), uma lista x,y (uma tabela FITS com X e Y, ou texto com um x y por linha), ou listas x e y em request-json. Até 96 MB. |
POST /api/url_upload | Só listas x e y (como o astroquery as envia): uma URL não é buscada. |
/api/submissions/ID | A submissão e o seu job: o job está lá desde a primeira consulta. |
/api/jobs/ID | processing, solving, success ou failure; todo job termina num dos dois últimos. |
/api/jobs/ID/calibration/ | ra, dec, radius, pixscale, orientation, parity, width_arcsec, height_arcsec, calculados como o nova faz. |
/api/jobs/ID/info/ · tags/ · machine_tags/ · objects_in_field/ · annotations/ | Os objetos de céu profundo no campo, com as suas posições em pixels e os raios em annotations. |
/wcs_file/ID | A solução TAN-SIP como arquivo FITS só com cabeçalho (wcs.fits). |
/corr_file/ID · /axy_file/ID · /rdls_file/ID | As estrelas identificadas, as estrelas detectadas, as estrelas de catálogo identificadas: tabelas FITS nas colunas do nova. |
/joblog/ID | O que o job fez, como texto. |
- Sempre às cegas. Dicas de escala, posição e paridade são aceitas e ignoradas: o solver não precisa de nenhuma, e uma dica errada não pode estragar uma solução.
- Pixels são os do nova:
(1, 1)é o centro do primeiro pixel armazenado, o canto superior esquerdo de um JPEG ou PNG (a sua orientação EXIF não aplicada) ou a primeira linha de um arquivo FITS, seja qual for o seuROWORDER. Aorientationmantém a peculiaridade do nova para envios JPEG, PNG e GIF, para que os programas que a revertem obtenham o mesmo ângulo que do nova. - Panoramas e imagens de todo o céu resolvidos com um modelo de projeção têm calibração mas não
wcs_file: nenhum TAN-SIP os comporta. - Nenhuma imagem é guardada. Um envio é descartado assim que as suas estrelas são encontradas, portanto
new_fits_filee as imagens anotada, vermelho-verde e de extração não são oferecidas. Os resultados de um job ficam em memória por 30 minutos, depois são esquecidos. - Limites: envios 20 de uma vez e 6 por minuto por endereço; as outras rotas contam como requisições leves (60 de uma vez, 60 por minuto).
Histórico de versões
- 1.2 (19 de outubro de 2026): resolução da Lua:
/api/v1/solve/moon. - 1.1 (17 de outubro de 2026): a API compatível com Astrometry.net.
- 1.0 (16 de outubro de 2026): resolver uma imagem (base64) ou posições de estrelas, anotar como SVG ou JSON, com o Sol, a Lua e os planetas.
Perguntas, um bug, uma cota maior? [email protected]. Ao usar a API você aceita os termos; o que ela faz com os seus dados está na página de privacidade.