MPC NEOCP Observations API¶
This tutorial provides information on how to use the Minor Planet Center's NEOCP Observations API.¶
The Minor Planet Center's NEOCP Observations service returns observational data for objects currently on the Near-Earth Object Confirmation Page (NEOCP, https://minorplanetcenter.net/iau/NEO/toconfirm_tabular.html).
This is useful when you want to:
- Retrieve observations for a candidate object on the NEOCP
- Plan follow-up observations of an unconfirmed NEO candidate
- Analyze the available astrometry for a NEOCP tracklet
Important: This API only works for objects currently on the NEOCP. Once an object is confirmed and removed from the NEOCP, use the standard Observations API instead.
The NEOCP Observations API is a REST endpoint. You can send GET requests to:
https://data.minorplanetcenter.net/api/get-obs-neocp
In the examples below we use Python code to query the API.
Further information and documentation can be found at:
Import Packages¶
Here we import the standard Python packages needed to call the API and interpret the returned data.
import requests
import json
import pandas as pd
API Parameters¶
The NEOCP Observations API accepts the following parameters:
| Parameter | Type | Required | Description | Default |
|---|---|---|---|---|
trksubs |
List (single string) | Yes | The tracklet identifier (temporary designation) on the NEOCP | None |
output_format |
List of strings | No | One or more of: XML, ADES_DF, OBS_DF, OBS80 |
XML |
ades_version |
String | No | ADES format version: 2017 or 2022 |
2022 |
Output Formats¶
- XML: Observations in ADES XML format
- OBS80: Observations in the classic MPC 80-column format
- ADES_DF: List of dictionaries with ADES field names (for pandas DataFrames)
- OBS_DF: List of dictionaries with MPC 80-column field names (for pandas DataFrames)
Finding NEOCP Tracklet Identifiers¶
To use this API, you need the tracklet identifier (temporary designation) of an object currently on the NEOCP.
You can find current NEOCP objects at:
The tracklet identifier is typically a 7-character code like P21Eetc or similar.
current_trksub = pd.read_html("https://minorplanetcenter.net/iau/NEO/toconfirm_tabular.html")[0].iloc[0]['Temp Desig']
print(f"A sample trksub currently on the NEOCP is: {current_trksub}")
Basic Query: OBS80 Format¶
Here we query for observations of a NEOCP object in the classic 80-column format.
Note: Replace the tracklet ID with a current NEOCP object for this to work.
response = requests.get(
"https://data.minorplanetcenter.net/api/get-obs-neocp",
json={"trksubs": [current_trksub], "output_format": ["OBS80"]}
)
if response.ok:
result = response.json()
if result and 'OBS80' in result[0]:
obs80_string = result[0]['OBS80']
print(f"Observations for {current_trksub}:")
print(obs80_string)
else:
print(f"No observations found or object not on NEOCP")
print(f"Response: {result}")
else:
print(f"Error: {response.status_code}")
print(f"The tracklet '{current_trksub}' may no longer be on the NEOCP.")
XML Format (ADES Standard)¶
The ADES XML format provides rich metadata about each observation.
trksub = "P21Eetc" # Replace with current NEOCP tracklet from https://minorplanetcenter.net/iau/NEO/toconfirm_tabular.html
response = requests.get(
"https://data.minorplanetcenter.net/api/get-obs-neocp",
json={"trksubs": [current_trksub], "output_format": ["XML"]}
)
if response.ok:
result = response.json()
if result and 'XML' in result[0]:
xml_string = result[0]['XML']
# Print first 1500 characters
print(xml_string[:1500])
if len(xml_string) > 1500:
print("\n... (truncated)")
else:
print("No XML data returned")
else:
print(f"Error: {response.status_code}")
Working with Pandas DataFrames¶
For analysis in Python, the ADES_DF and OBS_DF formats are most convenient.
response = requests.get(
"https://data.minorplanetcenter.net/api/get-obs-neocp",
json={"trksubs": [current_trksub], "output_format": ["ADES_DF", "OBS_DF"]}
)
if response.ok:
result = response.json()
if result and 'ADES_DF' in result[0]:
ades_df = pd.DataFrame(result[0]['ADES_DF'])
obs_df = pd.DataFrame(result[0]['OBS_DF'])
print(f"ADES DataFrame: {ades_df.shape[0]} observations, {ades_df.shape[1]} columns")
print(f"Columns: {list(ades_df.columns)}")
print("\nFirst few rows:")
display_cols = ['trksub', 'obstime', 'ra', 'dec', 'mag', 'stn']
available = [c for c in display_cols if c in ades_df.columns]
print(ades_df[available].head())
else:
print("No DataFrame data returned")
else:
print(f"Error: {response.status_code}")
ADES Version Parameter¶
You can specify which ADES version format to use. Note that the default for this API is 2022.
for version in ["2017", "2022"]:
response = requests.get(
"https://data.minorplanetcenter.net/api/get-obs-neocp",
json={
"trksubs": [current_trksub],
"output_format": ["ADES_DF"],
"ades_version": version
}
)
if response.ok:
result = response.json()
if result and 'ADES_DF' in result[0]:
df = pd.DataFrame(result[0]['ADES_DF'])
print(f"ADES {version}: {df.shape[1]} columns")
else:
print(f"ADES {version}: No data")
else:
print(f"ADES {version}: Error {response.status_code}")
Error Handling¶
When querying for a tracklet that is not on the NEOCP (either invalid or already removed), the API will return an empty result.
# Query for a non-existent tracklet
response = requests.get(
"https://data.minorplanetcenter.net/api/get-obs-neocp",
json={"trksubs": ["foobar"], "output_format": ["OBS80"]}
)
print(f"Status code: {response.status_code}")
print(f"Response OK: {response.ok}")
if response.ok:
print(f"Response content: {response.json()}")
else:
print(f"Error: Tracklet not found on NEOCP")
Helper Function¶
Here's a convenient helper function for querying NEOCP observations.
def get_neocp_observations(trksub, output_format="ADES_DF", ades_version="2017"):
"""
Retrieve observations for a NEOCP object.
Parameters
----------
trksub : str
The tracklet identifier on the NEOCP
output_format : str
One of 'ADES_DF', 'OBS_DF', 'XML', 'OBS80'
ades_version : str
ADES version: '2017' or '2022'
Returns
-------
pandas.DataFrame, str, or None
DataFrame for DF formats, string for XML/OBS80, None if not found
"""
response = requests.get(
"https://data.minorplanetcenter.net/api/get-obs-neocp",
json={
"trksubs": [trksub],
"output_format": [output_format],
"ades_version": ades_version
}
)
if not response.ok:
return None
result = response.json()
if not result or output_format not in result[0]:
return None
data = result[0][output_format]
if output_format in ["ADES_DF", "OBS_DF"]:
return pd.DataFrame(data)
return data
# Example usage
df = get_neocp_observations(current_trksub)
if df is not None:
print(f"Retrieved {len(df)} observations")
print(df.head())
else:
print(f"Object '{trksub}' not found on NEOCP")
Summary¶
The MPC NEOCP Observations API provides access to observations of objects currently on the Near-Earth Object Confirmation Page.
Key points:
- Endpoint:
https://data.minorplanetcenter.net/api/get-obs-neocp - Required parameter:
trksubs- list with the tracklet identifier - Output formats:
XML,OBS80,ADES_DF,OBS_DF - Default ADES version:
2022 - Only works for objects currently on the NEOCP
For confirmed objects, use the regular Observations API instead.
For questions or feedback, contact the MPC via the Jira Helpdesk.