A RESTful API built with TypeScript and Wrangler to query and analyze the NASA Meteorites Landings dataset.
You can found the original dataset here and by: NASA Open Data Portal
You can deploy your own instance of this API using the button below:
I host the project on the free plan, so it works well with medium and small datasets (see data/). However, the complete dataset may require a paid plan, especially if you intend to use the API at scale.
-
CORS: You're free to use the API in your website or any other project.
-
No sign-up, no credit card, or other personal information required.
-
No logs are maintained to track user activity (logs are only for debugging and performance).
-
Basic rate limiting implemented to prevent API abuse.
-
GDPR compliant: IP addresses are hashed using
SHA-256with a strong, secure key. -
Accurate search: You can apply multiple filters to tailor the request as precisely as needed.
-
This is a lightweight, highly optimized project for serverless environments that handles extensive computation.
The API is available here:
| Link: | Rate limit: | Owner: | Privacy Notice: | Dataset |
|---|---|---|---|---|
| https://meteorites.nde-code.workers.dev/ | 1 req/s | Nde-Code | privacy.md | 8.5K of entries |
And here is an overview of how my config.ts is currently configured for endpoints limitations:
| Code: | Value: | Description: | Note: |
|---|---|---|---|
MAX_RANDOM_METEORITES |
1000 | Maximum number of random meteorites. | If the requested count parameter exceeds this limit, an error will be returned. |
MAX_RETURNED_SEARCH_RESULTS |
500 | Maximum number of search results. | The search process will stop if the results exceed this limit. |
MIN_RADIUS |
1 | Minimum allowed radius. | If the radius parameter is below the minimum, an error will be returned. |
MAX_RADIUS |
2500 | Maximum allowed radius. | If the radius parameter exceeds the maximum, an error will be returned. |
DEFAULT_RANDOM_NUMBER_OF_METEORITES |
100 | Default number of random meteorites. | Default number returned when the count parameter is missing. |
Search meteorites using various filters, including name, class, date, mass, and geographic location.
| Parameter | Type | Description |
|---|---|---|
recclass |
string | Meteorite classification |
fall |
string | Fall status (Fell or Found) |
year |
number | Exact year the meteorite fell or was found |
minYear |
number | Minimum year for filtering |
maxYear |
number | Maximum year for filtering |
mass |
number | Exact mass in grams |
minMass |
number | Minimum mass in grams |
maxMass |
number | Maximum mass in grams |
centerLatitude |
number | Latitude of the center point for location filtering (required with radius) |
centerLongitude |
number | Longitude of the center point (required with radius) |
radius |
number | Radius in kilometers for location filtering (min: MIN_RADIUS, max: MAX_RADIUS) (required with center coords) |
limit |
number | Maximum number of search results (min: 1, max: MAX_RETURNED_SEARCH_RESULTS) |
Note: Invalid, non-required parameters will be completely ignored.
-
200 OK: Successful query with results. -
400 Bad Request: Missing or invalid parameters. -
404 Not Found: No meteorite data available. -
429 Too Many Requests: Rate limit exceeded. -
403 Forbidden: Unable to hash your IP. -
500 Internal Server Error: Wrong environment variable or server error.
curl "https://meteorites.nde-code.workers.dev/search?minYear=1998¢erLatitude=45.0¢erLongitude=5.0&radius=200"{
"success": {
"count": 1,
"meteorites": [
{
"id": "458",
"name": "Alby sur Chéran",
"recclass": "Eucrite-mmict",
"mass": 252,
"fall": "Fell",
"year": 2002,
"latitude": 45.82133,
"longitude": 6.01533
}
]
}
}Retrieve detailed information about a single meteorite by either its unique id or its exact name.
| Parameter | Type | Description |
|---|---|---|
id |
string | Unique identifier of the meteorite |
name |
string | Exact name of the meteorite (case-insensitive, normalized) |
Note: You must provide either
idorname. Supplying both parameters will result in an error. If neither is provided, the request will be rejected.
-
200 OK: Meteorite found and returned. -
400 Bad Request: Both parameters are missing or invalid. -
404 Not Found: No meteorite matches the given identifier. -
429 Too Many Requests: Rate limit exceeded. -
403 Forbidden: Unable to hash your IP. -
500 Internal Server Error: Wrong environment variable or server error.
Get meteorite by id:
curl "https://meteorites.nde-code.workers.dev/get?id=12345"Get meteorite by name:
curl "https://meteorites.nde-code.workers.dev/get?name=Kopjes%20Vlei"{
"success": {
"meteorite": {
"id": "12345",
"name": "Kopjes Vlei",
"recclass": "Iron, IIAB",
"mass": 13600,
"fall": "Found",
"year": 1914,
"latitude": -29.3,
"longitude": 21.15
}
}
}Get a random selection of meteorites.
Returns a randomly selected subset of meteorites, limited by a configurable maximum.
| Parameter | Type | Description |
|---|---|---|
count |
number | Number of random meteorites to return. Defaults to DEFAULT_RANDOM_NUMBER_OF_METEORITES. Cannot exceed MAX_RANDOM_METEORITES. |
Note: Invalid
countparameters will be ignored, and the default value will be applied.
-
200 OK: Successfully returns a random list of meteorites. -
400 Bad Request: Invalidcountparameter. -
404 Not Found: No meteorites data available. -
429 Too Many Requests: Rate limit exceeded. -
403 Forbidden: Unable to hash your IP. -
500 Internal Server Error: Wrong environment variable or server error.
curl "https://meteorites.nde-code.workers.dev/random?count=3"{
"success": {
"count": 3,
"meteorites": [
{
"id": "14764",
"name": "Mabwe-Khoywa",
"recclass": "L5",
"mass": 540,
"fall": "Fell",
"year": 1937,
"latitude": 19,
"longitude": 97
},
{
"id": "11442",
"name": "Guibga",
"recclass": "L5",
"mass": 288,
"fall": "Fell",
"year": 1972,
"latitude": 13.5,
"longitude": -0.68333
},
{
"id": "8671",
"name": "Elephant Moraine 90262",
"recclass": "L6",
"mass": 9.2,
"fall": "Found",
"year": 1990,
"latitude": -76.28752,
"longitude": 156.44737
}
]
}
}Retrieve aggregated statistics about the meteorite dataset stored.
Returns useful insights such as year ranges, mass stats, classification counts, and geolocation information.
| Field | Type | Description |
|---|---|---|
meteorites_count |
number | Total number of meteorites |
min_year, max_year |
string | Earliest and latest year of meteorite fall/found |
min_mass_g, max_mass_g |
number | Smallest and largest mass in grams |
avg_mass_g |
number | Average mass in grams (rounded to 2 decimal places) |
years |
string[] | Sorted list of all available years in the dataset |
years_distribution |
object | Frequency of each classification based on year |
recclasses |
string[] | Sorted list of unique meteorite classifications |
recclasses_distribution |
object | Frequency of each classification based on recclass |
geolocated_count |
number | Number of meteorites with valid latitude and longitude |
fall_counts |
object | Breakdown of meteorites by fall type: fell vs found |
Note: Some meteorites are recorded with a mass of 0 grams. This is not an error, but rather a reflection of specific characteristics such as extreme alteration, fossilization, or missing recoverable fragments. It's important to recognize that these cases do occur.
-
200 OK: Statistics successfully returned. -
404 Not Found: No meteorite data available. -
429 Too Many Requests: Rate limit exceeded. -
403 Forbidden: Unable to hash your IP. -
500 Internal Server Error: Wrong environment variable or server error.
curl "https://meteorites.nde-code.workers.dev/stats"{
"success": {
"meteorites_count": 8500,
"min_year": "860",
"max_year": "2013",
"min_mass_g": 0.1,
"max_mass_g": 60000000,
"avg_mass_g": 68231.78,
"years": [
"860",
"920",
"1399",
"1490",
"1491",
...
],
"years_distribution": {
"860": 1,
"920": 1,
"1399": 1,
"1490": 1,
"1491": 1,
...
}
"recclasses": [
"Acapulcoite",
"Achondrite-ung",
"Angrite",
"Aubrite",
...
],
"recclasses_distribution": {
"L6": 1616,
"H5": 1461,
"H6": 749,
"L5": 653,
"H4": 637,
...
},
"geolocated_count": 8500,
"fall_counts": {
"fell": 1095,
"found": 7405
}
}
}The project is a Cloudflare Workers application that uses the Cloudflare runtime called Workerd. The setup and code are not very different from a Node.js or Deno project, but there are a few things to keep in mind.
So, for that, I provide documentation here.
As explained above, this API works on data, and I designed something highly optimized. However, with limited resources, I had to make choices and reduce the dataset a little bit. Here are the different databases you can use if you deploy the project on your own instance:
-
The entire database (33K entries): meteorites_complete.json
-
The medium dataset (15K entries, reduced by grid filtering): meteorites_medium.json
-
The small dataset (used) (8.5K entries, reduced by grid filtering): meteorites_small.json
The small dataset is probably the best choice because the complete meteorites dataset contains a lot of noise. It depends on what you want to do with the project, but for statistics/visualization, the small dataset is likely the most suitable option.
If you need to create your own dataset, you can use the Python CLI (requires Python 3.8+, no external dependencies) with the following arguments:
| Argument | Description |
|---|---|
--input |
Path to the input meteorites.csv file (required) |
--output |
Path to the output JSON file (required) |
--grid |
Grid cell size in degrees (optional, > 0 enables grid filtering) |
--limit |
Maximum number of records (optional, 0 = unlimited) |
--clean-up (Recommended) |
Removes meteorite records with missing, invalid, or placeholder location data (e.g. reclat/reclong equal to 0.0 or GeoLocation set to (0.0, 0.0)), and normalizes empty metadata fields to ensure cleaner and more consistent output. |
--debug |
Debug level: 0 (silent), 1 (info), 2 (verbose) |
Navigate to the directory containing compiler.py and run the following command:
python compiler.py --input data/meteorites.csv --output data/my_db.json --clean-up --debug 2You can also get help directly in your terminal via:
python compiler.py --helpThis project is licensed under the Apache License v2.0.
Created and maintained by Nde-Code.
Feel free to reach out for questions or collaboration, or open an issue or pull request and I'll be happy to help.