Data & API · release v2026.09.25

Read the archive

A public bucket and a public API. No sign-up, no keys: read in bulk with LSDB, or one star at a time over HTTP.

01

Three collections, one pointer

Reference

Three HATS catalogs (HEALPix-partitioned Parquet), listed in catalogs/latest.json.

varchive_scalars
One row per star (10,304,679): ids (varchive_id, asas_sn_id, vsx_oid, name), VSX fields, coverage, features, periods, classification, crossmatches and reddening. No light curves.
curves_static
Frozen light curves: fixed data releases (OGLE, ASAS-3, MASCARA) and ASAS-SN's archival V band.
curves_live
Light curves a survey can still add to: ASAS-SN g, Gaia and ZTF. Same layout.

Collections are partitioned differently; join on varchive_id, not partition number. The pointer's shared path holds one link table per survey, links/<survey>.parquet: how each survey source was matched to a star (method, grade, separation, candidates, radius, magnitude check).

Where each survey's light curve is

Each row of curves_static and curves_live is one star: varchive_id, ra, dec and one nested column per survey, null when the star has no light curve from it. Every nested column has band, bjd_tdb, mag, mag_err, detected; the rest are the survey's own.

curves_static
columnsurveybandsits own columns
lc_asassn ASAS-SNVjd, limit, camera, quality, fwhm, image_id
lc_ogle OGLEI, V · series ii, iii, ivseries, hjd
lc_asas3 ASAS-3Vhjd, frame, dataset_block, grade, aperture
lc_mascara MASCARAVhjd, mag_delta
curves_live
columnsurveybandsits own columns
lc_asassn ASAS-SNgjd, limit, camera, quality, fwhm, image_id
lc_gaia GaiaG, BP, RP—
lc_ztf ZTFg, r, ihmjd, catflags, fieldid, rcid

ASAS-SN appears in both collections under the same column, lc_asassn: V epochs in one, g in the other. detected is false for a non-detection; only ASAS-SN and Gaia report them, so filter on it before using magnitudes. Use one band (and one OGLE series) at a time.

02

Read in bulk with LSDB

LSDB

lsdb reads only the partitions and columns you request, when you call .compute().

Pythonopen the release, filter, read a cone
import json, lsdb
from upath import UPath

root = UPath("https://data.varchive.app")
ptr = json.loads((root / "catalogs/latest.json").read_text())
path = lambda c: root / ptr["collections"][c]["path"]

# the scalars: one row per star
stars = lsdb.read_hats(path("varchive_scalars"),
                       columns=["varchive_id", "name", "ra", "dec", "vsx_broad_class",
                                "adopted_period", "adopted_survey", "is_periodic"])
rrl = stars.query("vsx_broad_class == 'RR_LYRAE' and is_periodic").compute()

# one survey's light curves around a position (radius in arcsec)
live = lsdb.read_hats(path("curves_live"), columns=["varchive_id", "lc_ztf"])
field = live.cone_search(ra=6.008, dec=38.577, radius_arcsec=60).compute()
field = field[field["lc_ztf"].notna()]   # the stars ZTF observed
lc = field["lc_ztf"].iloc[0]          # band, bjd_tdb, mag, mag_err, detected, hmjd, ...
r = lc[lc["band"] == "r"]             # one band at a time

Per-survey columns and snippets: ASAS-SN · Gaia · OGLE · ZTF · ASAS-3 · MASCARA. The scalars have index tables on varchive_id, asas_sn_id and name.

03

From a filter to light curves

LSDB

Select stars on any scalars column, then read any survey's light curves for just those stars. The second step reads only the partitions the selected stars sit in and matches on varchive_id.

  1. Filter varchive_scalars → the stars you want
  2. Fetch their partitions of curves_static / curves_live → one row per epoch
PythonRRab stars around M3, then their ZTF and ASAS-SN light curves
import json
import lsdb
import pandas as pd
from hats.pixel_math import HealpixPixel
from upath import UPath

root = UPath("https://data.varchive.app")
ptr = json.loads((root / "catalogs/latest.json").read_text())
path = lambda c: root / ptr["collections"][c]["path"]

# the collection(s) holding each survey's light curves (table above); the column is lc_<survey>
COLLECTIONS = {
    "asassn": ["curves_static", "curves_live"],   # V is static, g is live
    "gaia": ["curves_live"],
    "ztf": ["curves_live"],
    "ogle": ["curves_static"],
    "asas3": ["curves_static"],
    "mascara": ["curves_static"],
}

# 1. filter the scalars: here, periodic RRab stars within 2 degrees of M3
sel = lsdb.read_hats(
    path("varchive_scalars"),
    search_filter=lsdb.ConeSearch(ra=205.548, dec=28.377, radius_arcsec=7200),
    columns=["varchive_id", "name", "ra", "dec", "vsx_type", "adopted_period", "is_periodic"],
).query("vsx_type == 'RRAB' and is_periodic").compute()

# 2. one survey's epochs for those stars, one row per epoch
def light_curves(sel, survey):
    col = f"lc_{survey}"
    # sel's index is _healpix_29; >> 40 gives each star's order-9 HEALPix cell
    cells = {HealpixPixel(9, int(h) >> 40) for h in sel.index}
    tables = []
    for collection in COLLECTIONS[survey]:
        lc = lsdb.read_hats(path(collection), columns=["varchive_id", col],
                            search_filter=lsdb.PixelSearch(list(cells))).compute()
        lc = lc[lc["varchive_id"].isin(sel["varchive_id"]) & lc[col].notna()]
        tables.append(lc.set_index("varchive_id")[col].nest.to_flat().reset_index())
    return pd.concat(tables, ignore_index=True)

ztf = light_curves(sel, "ztf")        # varchive_id, band, bjd_tdb, mag, mag_err, detected, hmjd, ...
asassn = light_curves(sel, "asassn")  # V and g together, each row naming its band
ztf.to_parquet("m3_rrab_ztf.parquet")

# analyze one star in one band at a time
star = ztf[(ztf["varchive_id"] == sel["varchive_id"].iloc[0]) & (ztf["band"] == "r")]

As written, this selects 105 stars and returns ZTF light curves for 60 of them (46,638 epochs in g, r and i) in about 30 s. Swap in any survey ID; a survey with no light curves in the region returns an empty table. Without the cone, step 1 filters all 10,304,679 stars in about two minutes for a few columns (LSDB warns about the catalog's size, but reads only the columns you name). Step 2's cost follows the number of partitions the stars fall in, not the number of stars, so a selection spread over the whole sky reads most of that survey's column.

04

One star in Python

HTTP

For a few stars, use the API. Keys: varchive_id, ASAS-SN ID or VSX name.

PythonYY Crv: scalars and light curves
import io, requests
import pandas as pd

BASE = "https://api.varchive.app"

row = requests.get(f"{BASE}/star/YY Crv", params={"fields": "core,periods"}).json()["star"]
row["adopted_period"], row["period_source"], row["adopted_survey"], row["is_periodic"]

# one survey's epochs straight into a DataFrame, via the CSV export
csv = requests.get(f"{BASE}/star/YY Crv/lightcurve.csv", params={"survey": "asassn"}).text
lc = pd.read_csv(io.StringIO(csv), comment="#")
v = lc[lc["band"] == "V"]

# all surveys in one table, with a survey column
all_lc = pd.read_csv(io.StringIO(
    requests.get(f"{BASE}/star/YY Crv/lightcurve.csv", params={"survey": "all"}).text
), comment="#")
all_lc.groupby(["survey", "band"]).size()
05

The endpoints

HTTP

https://api.varchive.app, no key. {key} is a varchive_id, an ASAS-SN ID or a VSX name. Responses name the collection versions they read. Each example opens live.

requestreturns
GET/star/{key}?fields=coreThe star's scalars. fields picks column groups: core, periods, features, xmatch, all.
GET/star/{key}/lightcurve?survey=asassnOne survey's light curve as JSON. A 422 lists the surveys the star has; include_nondetections=true adds non-detections.
GET/star/{key}/lightcurve.csv?survey=allCSV with provenance and citation in the header (.vot for VOTable). survey=all puts every survey in one file, each row naming its survey and band.
GET/periodogram/{key}?unit=asassn:gStored GLS peaks for one survey band: unit is asassn:g, ogle:iv:I, …, or gaia:mb for Gaia's joint fit. The full periodogram comes with the star's primary light curve, the default when unit is omitted. kind=bls gives the BLS peaks.
GET/eclipses/{key}Predicted eclipses of an eclipsing binary, in BJD_TDB and UTC.
GET/search?…Filter the whole archive by class, period, magnitude, survey or position (below).
Shellfrom a terminal
# the star's core scalars
curl "https://api.varchive.app/star/YY%20Crv?fields=core"

# every survey's epochs in one CSV
curl "https://api.varchive.app/star/YY%20Crv/lightcurve.csv?survey=all" -o yy_crv.csv

Light curves include bjd_tdb, band, mag, mag_err, detected and native columns.

Uncached requests are limited per address, and heavier searches count more. A refused request gets 429 with Retry-After. For bulk work, read the collections with LSDB, which has no limit.

07

Time and magnitude systems

Reference

One time axis

Every epoch carries bjd_tdb (float64), converted from each survey's own clock. The native column stays beside it: jd for ASAS-SN, hmjd for ZTF, hjd for OGLE, ASAS-3 and MASCARA.

Never mix bands

Magnitudes stay in each survey's own band and system. Do not concatenate magnitudes across bands or surveys; combine them only with models that fit a separate offset per series.

Adopted periods and epochs are the archive's own; VSX values are kept for comparison.

08

Cite what you use

Reference

Cite the archive and each survey whose data you use. Star pages and exports list the references. AAVSO VSX and Gaia apply to every star. The archive's own data are under CC BY 4.0; each survey's data stay under the license below, and so do the catalogs and dust maps in the second table, whose values ride beside the light curves.

surveycitelicense
ASAS-SNpublic, no registration required (ASAS-SN Sky Patrol)
GaiaCC BY-SA 3.0 IGO (ESA Gaia data)
OGLEpublic, with the per-class discovery paper requested
ZTFpublic (IRSA/IPAC open data)
ASAS-3public
MASCARApublic (CDS/VizieR)
catalog or mapcitelicense
2MASScatalogpublic
AllWISEcatalogpublic
Bailer-Jones+2021 distancescatalogCC BY 4.0
TESS Input Catalogcatalogpublic
eROSITA-DE eRASS1catalogCC BY 4.0
SkyMapper DR4catalogCC BY 4.0
CatWISE2020catalogpublic
GALEX GUVcat_AIScatalogpublic
Pan-STARRS1 DR2catalogpublic
Hunt & Reffert 2023 clusterscatalogCC BY 4.0
CSFD dust mapdust mapCC BY 4.0
Edenhofer+2024 3D dust mapdust mapCC BY 4.0
Bayestar19 3D dust mapdust mapCC0 1.0
BibTeXthe archive
@misc{varchive,
  author       = {{varchive}},
  title        = {{varchive}: a multi-survey archive of light curves for {VSX} variable stars},
  howpublished = {\url{https://varchive.app}},
  note         = {Release v2026.09.25},
  year         = {2026},
}
09

Bring your own light curve

Browser

Analyze runs Lomb–Scargle, BLS, a fold, variability features and the classifier on your photometry in the browser. Nothing is uploaded.

Open Analyze →