User Guide
Using the Service:The Programmatic Results application programming interface (API) allows direct retrieval of transit prediction results in machine-readable formats, suitable for scripting and automated workflows. It accepts the same query parameters as the web version of the Transit Service.
This service also supports file uploads of custom target lists, which is described in the Upload a Target List File section of this page.
There are also ready-to-use examples of single-target and dataset queries and on this page, as well as known errors and their causes.
https://exoplanetarchive.ipac.caltech.edu/cgi-bin/TransitSearch/nph-transits-api
Use the &format= parameter to select the output format. The default is ipac.
| Format value | Description |
|---|---|
ipac | IPAC ASCII table format (default) |
json | JavaScript Object Notation object: {"stat":"OK","data":[...]} |
csv | Comma-separated values with a header row |
tsv | Tab-separated values with a header row |
The API operates in two modes depending on the type of query:
&sname= are executed synchronously. The result is returned directly in the HTTP response in the requested format.&extended=, &koi=, &k2=, &toi=) or file uploads (described below) are automatically executed asynchronously, because these searches can take several minutes to complete.You can override this behavior with the &async= parameter:
| Parameter | Effect |
|---|---|
&async=1 | Force asynchronous execution (also the default for dataset/upload queries). |
&async=0 | Force synchronous execution even for dataset or upload queries. The result is returned directly in the HTTP response. Use with caution: Large searches may exceed the server timeout (120 s for synchronous queries) and return an error. |
When a search is run asynchronously, the server starts the search in the background and immediately sends back a brief acknowledgment rather than making you wait. This acknowledgment contains a poll URL—a web address you can check back on to find out whether the search has finished.
Think of it like a ticket number at a deli counter: you hand in your order, receive a ticket, and check the board periodically until your number comes up.
An async request immediately returns an HTTP 202 response with a "PENDING" status and a poll_url:
{"stat": "PENDING", "job_id": "<id>", "poll_url": "...?job_id=<id>&format=json"}
Check the poll_url periodically (e.g., every 10–30 seconds) until the status changes. Each time you visit the poll_url you will receive one of three status values:
Response stat | Meaning |
|---|---|
"PENDING" | Search is still running—poll again later. |
"OK" | Search completed—results are included in the response. |
"ERROR" | Search failed—see the "msg" field for details. |
The poll_url honors the &format= parameter: append or change it at poll time to receive results in any supported format. You can also save the job_id from the initial response and construct the poll URL yourself later—job results are kept on the server for a reasonable period after the search completes.
Step 3a: Submit (dataset queries are automatically async):
https://exoplanetarchive.ipac.caltech.edu/cgi-bin/TransitSearch/nph-transits-api?extended=conf_all&begin=2460000.0&end=2460007.0&format=json
Response (immediate):
{
"stat": "PENDING",
"job_id": "3f2a1b4c-...",
"poll_url": "https://.../nph-transits-api?job_id=3f2a1b4c-...&format=json"
}
Step 3b: Poll the returned poll_url until "stat" is no longer "PENDING":
https://exoplanetarchive.ipac.caltech.edu/cgi-bin/TransitSearch/nph-transits-api?job_id=3f2a1b4c-...&format=json
Final response when complete:
{
"stat": "OK",
"data": [...]
}
Because dataset queries run asynchronously, the table below gives a rough guide to how long you should expect to wait before the poll URL returns "OK". Times were measured in May 2026 and will vary with server load. All figures are rounded up to the nearest 10 seconds.
| Dataset | Anywhere — next transit |
Anywhere — custom week |
Space obs (JWST) — next transit |
Ground obs — next transit |
|---|---|---|---|---|
| All confirmed planets ( extended=conf_all) |
~100 s | ~100 s | ~90 s | ~270 s |
| Confirmed transiting ( extended=conf_tran) |
~90 s | ~110 s | ~90 s | ~240 s |
| Confirmed RV ( extended=conf_rv) |
~30 s | ~30 s | ~30 s | ~100 s |
| All KOIs (conf + cand + FP) ( koi=koi_conf-koi_cand-koi_fp) |
~50 s | ~60 s | ~50 s | ~70 s |
| All K2 (conf + cand + FP) ( k2=k2_conf-k2_cand-k2_fp) |
~20 s | ~20 s | ~20 s | ~30 s |
| All TOIs ( toi=1) |
~50 s | ~70 s | ~50 s | ~290 s |
A few things to note:
extended=conf_all&koi=koi_conf&toi=1) will take longer than any single dataset—budget for the sum of the individual times as a conservative upper bound.If you force synchronous execution with &async=0, the server will abort and return an error after 120 seconds. Based on the table above, only small datasets (K2, confirmed RV) are reliably safe to run synchronously; most others risk hitting the timeout, particularly with a ground-based site.
You can query a single target by name, or select from a pre-defined dataset, which is a ready-to-use collection of targets maintained by the Exoplanet Archive (for example, all confirmed transiting planets, or all TESS Objects of Interest). Pre-defined datasets save you from having to supply a target list yourself; the archive keeps them up-to-date as new planets are confirmed.
| Parameter | Description | Example |
|---|---|---|
&sname= | Single target by name | &sname=HD+209458+b |
Pre-defined archive datasets—use extended=, koi=, k2=, or toi=1 with dash-separated sub-selections: | ||
&extended=conf_all | All confirmed planets | &extended=conf_all |
&extended=conf_tran | Confirmed transiting planets | &extended=conf_tran |
&extended=conf_rv | Confirmed RV planets | &extended=conf_rv |
&extended=conf_tran-conf_rv | Confirmed transiting and RV planets | &extended=conf_tran-conf_rv |
&toi=1 | TESS Objects of Interest | &toi=1 |
&koi=koi_conf | Confirmed Kepler Objects of Interest | &koi=koi_conf |
&koi=koi_cand | Candidate Kepler Objects of Interest | &koi=koi_cand |
&koi=koi_fp | False-positive Kepler Objects of Interest | &koi=koi_fp |
&koi=koi_conf-koi_cand-koi_fp | All KOI sub-lists combined | &koi=koi_conf-koi_cand-koi_fp |
&k2=k2_conf | Confirmed K2 Objects of Interest | &k2=k2_conf |
&k2=k2_cand | Candidate K2 Objects of Interest | &k2=k2_cand |
&k2=k2_fp | False-positive K2 Objects of Interest | &k2=k2_fp |
&k2=k2_conf-k2_cand-k2_fp | All K2 sub-lists combined | &k2=k2_conf-k2_cand-k2_fp |
Note: Multiple pre-defined datasets may be combined in a single request by including more than one dataset parameter, e.g., &extended=conf_all&koi=koi_conf&toi=1.
See also: Single-target examples • Dataset examples • File upload examples
For custom target lists that are not part of a pre-defined archive dataset, you may upload a plain-text file containing target names and/or sky coordinates. File uploads use an HTTP POST multipart request to the same API base URL.
Supported file extensions are .txt, .csv, and .tsv. The maximum number of targets per upload is 100, which will take around 15 minutes to return, due to the overhead incurred by individual target lookups.
Upload requests are always executed asynchronously—the immediate response will be a PENDING JSON with a poll_url to check back on.
Each non-blank, non-comment line is treated as one target. Comment lines begin with #. Three line formats are auto-detected:
| Format | Example line |
|---|---|
| Target name | HD 209458 b |
| RA / Dec (decimal degrees) | 83.8221 -5.3911 |
| Label + RA / Dec | MyTarget 83.8221 -5.3911 |
Fields may be separated by commas, tabs, or two or more spaces. Lines that cannot be parsed as RA/Dec are treated as target names.
Example file (my_targets.txt):
# Target name list HD 209458 b WASP-17 b # RA/Dec pairs (decimal degrees) 83.8221 -5.3911 # Labeled RA/Dec MyTarget 271.015 +44.500
Send a POST multipart/form-data request with the file attached under the field name targetfile. All other API parameters (e.g., nextTransit=1, format=, site=, etc.) are passed as URL query parameters in the normal way.
curl example:
curl -F "targetfile=@my_targets.txt" \ "https://exoplanetarchive.ipac.caltech.edu/cgi-bin/TransitSearch/nph-transits-api\ ?nextTransit=1&most_precise_ephem=1&format=json"
The immediate response is a PENDING JSON with a poll_url:
{
"stat": "PENDING",
"job_id": "3f2a1b4c-...",
"poll_url": "https://.../nph-transits-api?job_id=3f2a1b4c-...&format=json"
}
Poll the poll_url periodically until the status is "OK" or "ERROR" (see Asynchronous Response Workflow, above). The final "OK" response contains a "data" array with one entry per transit event found. Targets that could not be resolved or searched are included as stub entries with an "error" field instead of transit data.
import requests
import time
API = "https://exoplanetarchive.ipac.caltech.edu/cgi-bin/TransitSearch/nph-transits-api"
# ------------------------------------------------------------------
# Example 1: Single-target query (synchronous) — returns immediately
# ------------------------------------------------------------------
r = requests.get(API, params={
"sname": "HD 209458 b",
"nextTransit": "1",
"most_precise_ephem": "1",
"format": "json",
})
result = r.json()
for row in result["data"]:
print(row)
# ------------------------------------------------------------------
# Example 2: Single-target query, CSV format
# ------------------------------------------------------------------
r = requests.get(API, params={
"sname": "HD 209458 b",
"nextTransit": "1",
"most_precise_ephem": "1",
"format": "csv",
})
print(r.text) # CSV text with header row
# ------------------------------------------------------------------
# Example 3: Pre-defined dataset query (asynchronous — poll for results)
#
# Replace the dataset parameters to switch collections, e.g.:
# Confirmed planets: extended="conf_all"
# Confirmed transiting only: extended="conf_tran"
# TOIs: toi="1"
# Confirmed KOIs: koi="koi_conf"
# Confirmed + candidate KOIs:koi="koi_conf-koi_cand"
# K2 confirmed: k2="k2_conf"
# Multiple combined: extended="conf_all", koi="koi_conf", toi="1"
#
# Replace format= with "csv", "tsv", or "ipac" as needed.
# ------------------------------------------------------------------
def poll_job(poll_url, interval=15):
"""Poll poll_url every `interval` seconds until the job is done."""
while True:
time.sleep(interval)
r = requests.get(poll_url)
state = r.json()
print("Status:", state["stat"])
if state["stat"] != "PENDING":
return state
r = requests.get(API, params={
"extended": "conf_all",
"nextTransit": "1",
"format": "json",
})
job = r.json()
print("Job submitted:", job["job_id"])
print("Poll URL: ", job["poll_url"])
state = poll_job(job["poll_url"])
if state["stat"] == "OK":
for row in state["data"]:
print(row)
else:
print("Error:", state.get("msg"))
# ------------------------------------------------------------------
# Example 4: Pre-defined dataset, CSV format (change format= at poll time)
# ------------------------------------------------------------------
r = requests.get(API, params={
"toi": "1",
"nextTransit": "1",
"format": "csv", # format is remembered in the poll_url
})
job = r.json()
state = poll_job(job["poll_url"])
if state["stat"] == "OK":
print(state) # for non-JSON formats the body is plain text, not a dict
# use requests.get(job["poll_url"]).text to retrieve it
# ------------------------------------------------------------------
# Example 5: Uploaded target list (asynchronous POST)
# ------------------------------------------------------------------
with open("my_targets.txt", "rb") as f:
r = requests.post(
API + "?nextTransit=1&most_precise_ephem=1&format=json",
files={"targetfile": f},
)
job = r.json()
print("Upload job:", job["job_id"])
state = poll_job(job["poll_url"])
if state["stat"] == "OK":
for row in state["data"]:
# Targets that failed to resolve have an "error" key instead of transit data
if "error" in row:
print("Failed:", row)
else:
print(row)
else:
print("Error:", state.get("msg"))
| Parameter | Description | Example |
|---|---|---|
&nextTransit=1 | Next transit only (default) | &nextTransit=1 |
&begin= | Start of time range (JD) | &begin=2460000.0 |
&end= | End of time range (JD) | &end=2460007.0 |
See also: Dataset examples (date-range queries)
Refer to the Transit Service Query Form for named observatories, for which you can use formats like &site=kitt_peak or &site=Kitt Peak.
For custom lat/lon location, you can optionally set observatory name with &obsname=MyObservatory&lat=31.9&lon=-111.6.
| Parameter | Description | Example |
|---|---|---|
&site= | Named observatory | &site=kitt_peak |
&space_obs= | Space observatory | &space_obs=jwst |
&lat= &lon= | Custom latitude/longitude | &lat=31.9&lon=-111.6 |
See also: Observer location examples
| Parameter | Description | Example |
|---|---|---|
&phases= | Comma-separated phase list | &phases=0.0,0.5 |
See also: Orbital phase example
| Parameter | Description | Example |
|---|---|---|
&most_precise_ephem=1 | Use the most precise available ephemeris | &most_precise_ephem=1 |
&default_ephem=1 | Use the default archive ephemeris | &default_ephem=1 |
&customParams=1 | Use custom ephemeris parameters (see below) | &customParams=1 |
See also: Custom ephemeris example
When using &customParams=1, the following parameters override the archive ephemeris:
| Parameter | Description | Example |
|---|---|---|
&period= | Orbital period (days) | &period=3.52474 |
&tranmid= | Transit midpoint (JD) | &tranmid=2452826.628 |
&tdur= | Transit duration (hours) | &tdur=3.1 |
&tranmiderr= | Midpoint uncertainty (days) | |
&eccen= | Eccentricity | |
&semim= | Semimajor axis (au) | |
&srad= | Stellar radius (solar radii) | |
&prad= | Planet radius (Jupiter radii) |
See also: Custom ephemeris example
| Parameter | Description | Example |
|---|---|---|
&vis_alt= | Minimum target altitude (degrees) | &vis_alt=30 |
&vis_air= | Maximum airmass | &vis_air=2.0 |
&twilight= | Twilight angle (degrees, negative below horizon) | &twilight=-12 |
See also: Observer location examples (include visibility constraints)
Next transit, returned as default IPAC table format:
https://exoplanetarchive.ipac.caltech.edu/cgi-bin/TransitSearch/nph-transits-api?sname=HD+209458+b&nextTransit=1&most_precise_ephem=1
Next transit, returned as JSON:
https://exoplanetarchive.ipac.caltech.edu/cgi-bin/TransitSearch/nph-transits-api?sname=HD+209458+b&nextTransit=1&most_precise_ephem=1&format=json
Next transit, returned as CSV:
https://exoplanetarchive.ipac.caltech.edu/cgi-bin/TransitSearch/nph-transits-api?sname=HD+209458+b&nextTransit=1&most_precise_ephem=1&format=csv
poll_url)All confirmed planets over a date range, returned as IPAC table:
https://exoplanetarchive.ipac.caltech.edu/cgi-bin/TransitSearch/nph-transits-api?extended=conf_all&begin=2460000.0&end=2460007.0&format=ipac
Confirmed transiting planets over a date range, returned as IPAC table:
https://exoplanetarchive.ipac.caltech.edu/cgi-bin/TransitSearch/nph-transits-api?extended=conf_tran&begin=2460000.0&end=2460007.0&format=ipac
TESS Objects of Interest, next transit, returned as CSV:
https://exoplanetarchive.ipac.caltech.edu/cgi-bin/TransitSearch/nph-transits-api?toi=1&nextTransit=1&format=csv
Confirmed and candidate KOIs, next transit, returned as TSV:
https://exoplanetarchive.ipac.caltech.edu/cgi-bin/TransitSearch/nph-transits-api?koi=koi_conf-koi_cand&nextTransit=1&format=tsv
All K2 sub-lists combined, next transit, returned as default IPAC table format:
https://exoplanetarchive.ipac.caltech.edu/cgi-bin/TransitSearch/nph-transits-api?k2=k2_conf-k2_cand-k2_fp&nextTransit=1
Force synchronous execution for a small dataset (returns immediately, but may time out for large searches), returned as CSV:
https://exoplanetarchive.ipac.caltech.edu/cgi-bin/TransitSearch/nph-transits-api?toi=1&nextTransit=1&format=csv&async=0
Single target observed from Kitt Peak with visibility constraints, returned as CSV:
https://exoplanetarchive.ipac.caltech.edu/cgi-bin/TransitSearch/nph-transits-api?sname=HD+209458+b&nextTransit=1&site=kitt_peak&vis_alt=30&twilight=-12&format=csv
Single target observed from a custom latitude/longitude, returned as TSV:
https://exoplanetarchive.ipac.caltech.edu/cgi-bin/TransitSearch/nph-transits-api?sname=HD+209458+b&nextTransit=1&lat=31.9&lon=-111.6&format=tsv
JWST observing windows for a single target, returned as JSON:
https://exoplanetarchive.ipac.caltech.edu/cgi-bin/TransitSearch/nph-transits-api?sname=HD+209458+b&nextTransit=1&space_obs=jwst&format=json
Single target with custom ephemeris parameters overriding the archive values, returned as JSON:
https://exoplanetarchive.ipac.caltech.edu/cgi-bin/TransitSearch/nph-transits-api?sname=HD+209458+b&nextTransit=1&customParams=1&period=3.52474&tranmid=2452826.628&tdur=3.1&format=json
Primary and secondary transits (phases 0.0 and 0.5) for a single target, returned as JSON:
https://exoplanetarchive.ipac.caltech.edu/cgi-bin/TransitSearch/nph-transits-api?sname=HD+209458+b&nextTransit=1&phases=0.0,0.5&format=json
poll_url)Custom target list, next transit, returned as JSON:
curl -F "targetfile=@my_targets.txt" \ "https://exoplanetarchive.ipac.caltech.edu/cgi-bin/TransitSearch/nph-transits-api\ ?nextTransit=1&most_precise_ephem=1&format=json"
Custom target list observed from Kitt Peak with visibility constraints, returned as CSV:
curl -F "targetfile=@my_targets.txt" \ "https://exoplanetarchive.ipac.caltech.edu/cgi-bin/TransitSearch/nph-transits-api\ ?nextTransit=1&site=kitt_peak&vis_alt=30&twilight=-12&format=csv"
Errors are always returned as JSON regardless of the requested format:
{"stat": "ERROR", "msg": "..."}
Common upload-specific errors:
| Message | Cause |
|---|---|
Unsupported file type '.xyz'. Please upload one of: .txt, .csv, .tsv. | Wrong file extension. |
Uploaded file contains no valid targets. | File was empty or contained only comments. |
Uploaded file contains N targets; the maximum allowed is 500. | File exceeds the per-request target limit. |
«Previous Building a Transit Service Query by URL Viewing Predictions Next »
Last updated: 1 June 2026