NASA Earthdata Search: Satellite Datasets and Data Files avatar

NASA Earthdata Search: Satellite Datasets and Data Files

Pricing

from $1.40 / 1,000 metadata row returneds

Go to Apify Store
NASA Earthdata Search: Satellite Datasets and Data Files

NASA Earthdata Search: Satellite Datasets and Data Files

Search NASA's Earth-science metadata catalog without a key: datasets by keyword, mission, instrument, data center, processing level, bounding box and time range, or the single data files of a dataset with size, day/night flag, footprint and download, S3 and OPeNDAP links.

Pricing

from $1.40 / 1,000 metadata row returneds

Rating

0.0

(0)

Developer

Samat Makatov

Samat Makatov

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 days ago

Last modified

Share

Search NASA's Earth-science metadata catalog without a key: datasets by keyword, mission, instrument, data center, processing level, bounding box and time range, or the single data files of a dataset with size, day/night flag, footprint and download, S3 and OPeNDAP links.

Every Earth observation dataset NASA distributes is registered in the Common Metadata Repository, the index behind the Earthdata Search website: 58 data centers (provider ids read on 2026-10-07), their datasets, and every single file of every dataset. This actor turns that index into dataset rows. In collections mode one row is one dataset — title, short name, concept id, publishing data center, satellites, processing level, period covered, footprint and how many files the archive holds. In granules mode one row is one data file — its acquisition window, size in megabytes, footprint, and its HTTPS download, s3://, OPeNDAP and browse-image addresses.

It reads metadata only and never downloads a data file: the file's address ends up in your row, so a file that needs a free Earthdata Login account still gives you a usable link. No API key, no account, no cookie, no browser, no proxy. All dates are UTC ISO-8601.

Need it tailored to your workflow? Missing a field, a filter, another source or a different output format? Open an issue and describe what you need — we read every request and adapt the actor.

Use cases

  • Find the dataset behind a question. A fire, water or air-quality analyst types wildfire, soil moisture or air quality into query, switches withGranulesOnly on, and gets the datasets that really hold data, with their file counts.
  • Inventory one mission or one archive. A remote-sensing team lists everything MODIS on Terra produced inside the land-processes archive (platforms, instruments, providers) ordered by how much people download it — an internal catalog in one run.
  • See what covers your area. A regional GIS or environment agency sets boundingBox (or point for a single city) plus processingLevels 3 and 4 and gets the analysis-ready products whose footprint overlaps the area.
  • Get the files for an area and a week. A data engineer switches to granules, names the dataset in shortNames, sets the box and the two dates, and gets one row per file with the download, S3 and OPeNDAP links to feed a pipeline.
  • Watch a dataset for new files. A scheduled task in granules mode with one shortNames value, sort on newest first, onlyNew on and a small maxItems writes only the files that appeared since the previous run — and pays for nothing else.
  • Feed an agent or a pipeline. Set fields to four or five columns and maxSummaryChars to 0: short rows with the permanent conceptId as the key, cheap enough to call on every question.
  • Size a download before you pay for it. granuleCount says how many files a dataset holds, so you know in advance whether a granules run on it is 40 rows or four million.

Input

Every field is optional. The prefill is query: "wildfire" — run the actor as it comes and you get 25 wildfire datasets.

FieldTypeDefaultAllowed values / notes
modestring (enum)collectionscollections (one row per dataset) or granules (one row per data file). A granules run needs shortNames or conceptIds. Strict: the platform refuses any other value before the run starts.
querystring(prefill wildfire)Free-text search over dataset title, summary, science keywords, mission and instrument names. Sent to the source. collections mode only — the catalog has no free-text search over files.
shortNamesstring[](empty)The dataset's own short name: MOD11A1, VNP46A2, MUR-JPL-L4-GLOB-v4.1. At most 20, OR-combined. Checked against the catalog first; see Dataset short names.
conceptIdsstring[](empty)The catalog's permanent dataset id, C<digits>-<DATACENTER>. At most 20, OR-combined. Checked against the catalog first.
platformsstring[](empty)Satellite or mission names, at most 10, OR-combined. Sent to the source. See Satellites and platforms.
instrumentsstring[](empty)Sensor names, at most 10, OR-combined. Sent to the source. See Instruments.
providersstring[](empty)Data-center ids, at most 10, OR-combined. Sent to the source as the provider filter. See Data centers.
processingLevelsstring[] (enum)(empty = all)0, 1, 1A, 1B, 1C, 1T, 2, 2G, 2P, 3, 4, NA. Sent to the source. collections mode only. Strict: an off-list value is refused by the platform before the run.
boundingBoxstring(empty)west,south,east,north in degrees, e.g. 46,40,88,56. Sent to the source. Overlap, not containment.
pointstring(empty)longitude,latitude, e.g. 76.889,43.238. Sent to the source. Ignored when boundingBox is also set (the run says so).
temporalFromstring(empty)2026-09-01 or 2026-09-01T00:00:00Z, read as UTC. Sent to the source.
temporalTostring(empty)Same format, inclusive, UTC. Sent to the source.
cloudHostedOnlybooleanfalseKeep only datasets the archive moved into cloud storage (their files carry s3:// links). Sent to the source. collections mode only.
downloadableOnlybooleanfalseKeep only records the catalog marks as having online access to the data. Sent to the source, both modes.
withGranulesOnlybooleanfalseKeep only datasets that already hold at least one file. Sent to the source. collections mode only.
sortstring (enum)relevancerelevance, newestData, oldestData, mostUsed, title. See Sort orders. Strict enum.
onlyNewbooleanfalseRemember the concept ids this run wrote and, next run of the same actor or task, write only ids that were not written before. Applied by this actor.
maxItemsinteger251–2000. Hard cap on the rows written, and therefore on what the run costs.
includeGranuleCountsbooleantrueFill the granuleCount column. Costs no extra request. collections mode only.
maxSummaryCharsinteger12000–20000. The summary column is cut to this many characters at a word boundary; 0 leaves the column out of the row. collections mode only.
fieldsstring[](all)Keep only the named columns, in this order. rowType, conceptId, title, url and fetchedAt are always kept — the ones you do not name come first, and one you do name moves to the position you gave it. Letter case does not matter; a name this mode has no column for is reported in the status message, and a list with no real column at all is refused.

Free-text fields and strict enum fields are different. shortNames, conceptIds, platforms, instruments and providers are free text: case, surrounding spaces, accents, _/-/space differences and the aliases listed below are all accepted, and any other spelling is refused with the closest known values in the message — never swapped for something else, because a near miss is another dataset as often as a typo. mode, sort and processingLevels are enum fields: the Apify platform refuses an off-list value with HTTP 400 before the run starts, so there is no typo correction for them and the allowed values must be written exactly as listed.

Reference

Sort orders

Valuecollectionsgranules
relevancethe source's own ranking (only meaningful together with query)the source's own order
newestDatadatasets whose data starts latest firstnewest file first — the order a watch task wants
oldestDataearliest data firstoldest file first
mostUseddatasets people download most firstno equivalent: the run orders files newest first instead and says so in its status message
titledataset title, A to Zfile name, A to Z

Processing levels

ValueWhat it is
0Raw instrument data, unprocessed.
1, 1A, 1B, 1C, 1TInstrument measurements — radiances and brightness values, with calibration and geolocation added at the later letters.
2, 2PGeophysical values (temperature, moisture, concentration) along the satellite's own track.
2GThe same, resampled onto a grid but still per orbit.
3Gridded and averaged over space and time — the usual choice for a map.
4Model or analysis output that blends several sources, e.g. a reanalysis.
NAThe publisher gave no level.

An off-list value here is refused by the platform before the run starts, with the allowed values in the error.

Data centers

The providers input takes the catalog's own data-center id, which is exactly what the dataCenter column of every row carries. The ones people ask for most:

IdArchives
LPCLOUDLand products: MODIS and VIIRS land, ECOSTRESS, EMIT, Landsat-derived surface reflectance.
LAADSAtmosphere and calibrated radiances, and the VIIRS nighttime-lights products.
POCLOUDPhysical oceanography: sea surface temperature, sea level, salinity, ocean winds.
NSIDC_ECS, NSIDC_CPRDSnow, ice, glaciers, frozen ground, ICESat-2 and SMAP.
GES_DISC, GESDISCCLDAtmospheric composition, water and energy cycle, MERRA-2 and GPM.
ORNL_CLOUD, ORNL_DAACBiogeochemistry, vegetation, carbon and field campaigns.
ASFSynthetic-aperture radar: Sentinel-1, ALOS, NISAR.
LARC_CLOUD, LARC_ASDCClouds, aerosols, radiation budget, tropospheric chemistry.
OB_DAAC, OB_CLOUD, OBPGOcean biology and ocean colour.
SEDACHuman dimensions: population, settlements, health and climate.
GHRC, GHRC_CLOUDHydrology, lightning, severe weather field campaigns.
USGS_EROS, USGS_LTAUSGS-held Landsat and land-imaging collections.
SCIOPSOlder campaign and partner records registered without a cloud archive.
LANCEMODIS, LANCEAMSR2, OMINRTNear-real-time streams, hours after acquisition.
ESA, EUMETSAT, JAXA, ISRO, INPE, CCMEOPartner agency records registered in the same catalog.

Fifty-eight ids exist in total; the run refuses an id the catalog does not have and names the closest ones. Spoken names are accepted as aliases: PO.DAAC → POCLOUD, LP DAAC / LPDAAC → LPCLOUD, NSIDC → NSIDC_ECS, GES DISC → GES_DISC, ORNL → ORNL_CLOUD, ASDC → LARC_ASDC, FIRMS → LM_FIRMS, NCEI → NOAA_NCEI, Alaska Satellite Facility → ASF. Two spellings that look like aliases are ids of their own and stay as typed: PODAAC and ORNL_DAAC are the older, non-cloud archives of the same institutions.

Satellites and platforms

Spelled as the catalog spells them (case and spaces do not matter):

Terra, Aqua, Suomi-NPP, NOAA-20, NOAA-21, Landsat-5, Landsat-7, Landsat-8, Landsat-9, Sentinel-1A, Sentinel-1B, Sentinel-2A, Sentinel-2B, Sentinel-3A, Sentinel-3B, Sentinel-5P, Sentinel-6A, ICESat, ICESat-2, SMAP, GPM, TRMM, GRACE, GRACE-FO, CALIPSO, CloudSat, Aura, OCO-2, OCO-3, ISS, Nimbus-7, JASON-1, JASON-2, JASON-3, TOPEX/POSEIDON, SWOT, NISAR, PACE, GOES-16, GOES-17, GOES-18, METOP-A, METOP-B, METOP-C, ENVISAT, ERS-1, ERS-2, ALOS, RADARSAT-1, Aquarius_SAC-D.

The catalog also uses non-satellite platform words, and they work the same way: AIRCRAFT, BUOYS, FIELD SURVEYS, MODELS, COMPUTERS, NOT APPLICABLE. Aliases include snpp / npp → Suomi-NPP, Sentinel-6 and Sentinel-6 Michael Freilich → Sentinel-6A, Aquarius → Aquarius_SAC-D, TOPEX → TOPEX/POSEIDON, International Space Station → ISS.

The catalog's full platform vocabulary is far longer than this list. A name that is not listed here is checked against the catalog itself before the run searches: if some dataset really uses it, the run accepts it as typed; if nothing does, the run stops with the closest names from the list above. That check costs one extra request per unlisted name.

Instruments

MODIS, VIIRS, ASTER, MISR, MOPITT, AIRS, AMSU-A, AMSR-E, AMSR2, ATLAS, OLI, OLI-2, TIRS, TIRS-2, ETM+, TM, MSS, SAR, PALSAR, SLSTR, OLCI, SRAL, TROPOMI, OMI, OMPS, MLS, TES, GMI, DPR, PR, TMI, ECOSTRESS, GEDI, AVHRR, SeaWiFS, OCI, ABI, POSEIDON-3, SMAP L-BAND RADAR, LIDAR, SPECTROMETERS. Aliases: ETM → ETM+, AMSR-2 → AMSR2. Unlisted names are checked against the catalog, exactly as for the platforms.

Dataset short names

Worth knowing, all checked against the catalog on 2026-10-07:

Short nameDatasetData center
MOD11A1MODIS/Terra daily land surface temperature, 1 km gridLPCLOUD
MOD09GAMODIS/Terra daily surface reflectance, 1 km gridLPCLOUD
MYD09GAThe same from AquaLPCLOUD
VNP46A2VIIRS Black Marble gap-filled nighttime lights, dailyLAADS
MUR-JPL-L4-GLOB-v4.1MUR global sea surface temperature analysis, 1 kmPOCLOUD
MUR25-JPL-L4-GLOB-v04.2The same at 25 km, lighter filesPOCLOUD
OSTIA-UKMO-L4-GLOB-REP-v2.0OSTIA reprocessed sea surface temperaturePOCLOUD
SPL3SMP_ESMAP enhanced soil moisture, 9 km gridNSIDC_CPRD
SPL4SMGPSMAP level-4 surface and root-zone soil moistureNSIDC_CPRD
M2SMNXEDIMERRA-2 extreme precipitation and temperature indicesGES_DISC

A short name the catalog does not know never becomes a wider search: it gets its own row with found: false and a note on what to do instead (and that row is billed like any other).

Bounding boxes to start from

AreaboundingBox
Kazakhstan and Central Asia46,40,88,56
Contiguous United States-125,24,-66,50
Western Europe-10,35,30,60
Amazon basin-79,-18,-44,6
Sub-Saharan Africa-18,-35,52,16
South and East Asia60,5,150,55
Arctic Ocean-180,66,180,90

A dataset or file matches when its own footprint overlaps the box, so a global dataset matches every box — that is the source's rule, not ours.

Examples

Which NASA datasets exist about wildfire, and do they hold files?

{ "mode": "collections", "query": "wildfire", "withGranulesOnly": true, "includeGranuleCounts": true, "maxItems": 20 }

Sea surface temperature datasets a cloud job can read directly

{ "mode": "collections", "query": "sea surface temperature", "cloudHostedOnly": true, "downloadableOnly": true, "maxItems": 20 }

Everything MODIS/Terra in the land-processes archive, most used first

{ "mode": "collections", "providers": ["LPCLOUD"], "platforms": ["Terra"], "instruments": ["MODIS"], "withGranulesOnly": true, "sort": "mostUsed", "maxItems": 25 }

Analysis-ready products covering Central Asia, with data since 2020

{ "mode": "collections", "boundingBox": "46,40,88,56", "temporalFrom": "2020-01-01", "processingLevels": ["3", "4"], "maxItems": 20 }

The MODIS land-surface-temperature files over a box and three days

{ "mode": "granules", "shortNames": ["MOD11A1"], "boundingBox": "70,40,80,50", "temporalFrom": "2026-09-01", "temporalTo": "2026-09-03", "sort": "newestData", "maxItems": 20 }

The files of one dataset by its permanent concept id, A to Z

{ "mode": "granules", "conceptIds": ["C1748058432-LPCLOUD"], "sort": "title", "maxItems": 10 }

The newest nighttime-lights files, as a daily watch task

{ "mode": "granules", "shortNames": ["VNP46A2"], "sort": "newestData", "onlyNew": true, "maxItems": 20 }

Short rows for an agent: ids, data center and size only

{ "mode": "collections", "query": "soil moisture", "withGranulesOnly": true, "maxSummaryChars": 0,
"fields": ["title", "shortName", "dataCenter", "granuleCount", "timeStart"], "maxItems": 20 }

Output

One real dataset row from the cloud run 4uT0wCs5LO6aOArAZ (long arrays and the summary trimmed with … by the sampler):

{
"rowType": "collection",
"conceptId": "C1748058432-LPCLOUD",
"title": "MODIS/Terra Land Surface Temperature/Emissivity Daily L3 Global 1km SIN Grid V061",
"url": "https://search.earthdata.nasa.gov/search/granules?p=C1748058432-LPCLOUD",
"fetchedAt": "2026-10-07T22:50:53.654Z",
"shortName": "MOD11A1",
"versionId": "061",
"entryId": "MOD11A1_061",
"dataCenter": "LPCLOUD",
"archiveCenter": "LP DAAC",
"organizations": [
"LP DAAC",
"NASA/GSFC/SED/ESD/TISL/MODAPS"
],
"platforms": [
"Terra"
],
"processingLevel": "3",
"collectionDataType": "SCIENCE_QUALITY",
"consortiums": [
"GEOSS",
"EOSDIS"
],
"granuleCount": 3049436,
"cloudHosted": true,
"onlineAccess": true,
"hasBrowse": true,
"timeStart": "2000-02-24T00:00:00.000Z",
"timeEnd": null,
"ongoing": true,
"boxes": [
"-90 -180 90 180"
],
"polygons": [],
"points": [],
"coordinateSystem": "CARTESIAN",
"originalFormat": "UMM_JSON",
"revisionDate": "2021-02-04T00:00:00.000Z",
"doiUrl": "https://doi.org/10.5067/MODIS/MOD11A1.061",
"documentationUrls": [
"https://lpdaac.usgs.gov/documents/119/MOD11_ATBD.pdf",
"https://lpdaac.usgs.gov/documents/715/MOD11_User_Guide_V61.pdf",
"https://ladsweb.modaps.eosdis.nasa.gov/filespec/MODIS/61/MOD11A1",
"https://modis-land.gsfc.nasa.gov/ValStatus.php?ProductID=MOD11",
"https://modis-land.gsfc.nasa.gov/MODLAND_val.html",
"…"
],
"source": "cmr.earthdata.nasa.gov",
"summary": "The Terra Moderate Resolution Imaging Spectroradiometer (MODIS) Land Surface Temperature/Emissivity Daily (MOD11A1) Version 6.1 product provides daily per-pixel Land Surface Temperature and Emissivity…"
}

And one real data-file row, from the cloud run ec7jskhpiWkgK13vE:

{
"rowType": "granule",
"conceptId": "G4298541041-LPCLOUD",
"title": "MOD11A1.A2026246.h22v04.061.2026247201930",
"url": "https://search.earthdata.nasa.gov/search/granules?p=C1748058432-LPCLOUD",
"fetchedAt": "2026-10-07T22:50:58.268Z",
"producerGranuleId": "MOD11A1.A2026246.h22v04.061.2026247201930",
"granuleUr": "MOD11A1.A2026246.h22v04.061.2026247201930",
"collectionConceptId": "C1748058432-LPCLOUD",
"datasetTitle": "MODIS/Terra Land Surface Temperature/Emissivity Daily L3 Global 1km SIN Grid V061",
"dataCenter": "LPCLOUD",
"dayNightFlag": "BOTH",
"granuleSizeMb": 6.4578,
"timeStart": "2026-09-03T00:00:00.000Z",
"timeEnd": "2026-09-03T23:59:59.000Z",
"boxes": [],
"polygons": [
"39.834 52.0142 39.7925 65.168 49.9983 77.8098 50.0583 62.1214 39.834 52.0142"
],
"points": [],
"coordinateSystem": "GEODETIC",
"onlineAccess": true,
"hasBrowse": true,
"originalFormat": "ECHO10",
"revisionDate": "2026-09-04T20:53:04.983Z",
"downloadUrls": [
"https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/MOD11A1.061/MOD11A1.A2026246.h22v04.061.2026247201930/MOD11A1.A2026246.h22v04.061.2026247201930.hdf"
],
"s3Urls": [
"s3://lp-prod-protected/MOD11A1.061/MOD11A1.A2026246.h22v04.061.2026247201930/MOD11A1.A2026246.h22v04.061.2026247201930.hdf"
],
"opendapUrl": "https://opendap.earthdata.nasa.gov/collections/C1748058432-LPCLOUD/granules/MOD11A1.A2026246.h22v04.061.2026247201930",
"browseUrls": [
"https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-public/MOD11A1.061/MOD11A1.A2026246.h22v04.061.2026247201930/BROWSE.MOD11A1.A2026246.h22v04.061.2026247201933.1.jpg",
"https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-public/MOD11A1.061/MOD11A1.A2026246.h22v04.061.2026247201930/BROWSE.MOD11A1.A2026246.h22v04.061.2026247201933.2.jpg"
],
"metadataUrls": [
"https://data.lpdaac.earthdatacloud.nasa.gov/lp-prod-protected/MOD11A1.061/MOD11A1.A2026246.h22v04.061.2026247201930/MOD11A1.A2026246.h22v04.061.2026247201930.cmr.xml",
"https://data.lpdaac.earthdatacloud.nasa.gov/s3credentials",
"https://www.earthdata.nasa.gov/centers/lp-daac"
],
"doiUrl": "https://doi.org/10.5067/MODIS/MOD11A1.061",
"needsEarthdataLogin": true,
"source": "cmr.earthdata.nasa.gov"
}

Always present, in both modes

FieldTypeMeaning
rowTypestringcollection, granule, or notFound for a marker row.
conceptIdstringThe catalog's permanent id of the dataset (C…) or the file (G…). Empty only on a marker row.
titlestringDataset title, or the producer's file name.
urlstringThe catalog's own public page for the dataset and its files.
fetchedAtstringWhen this run read the record, UTC.

Dataset rows (collections)

FieldTypeMeaning
shortName, versionId, entryIdstringThe dataset's short name, version and the two joined.
summarystringThe publisher's description, cut to maxSummaryChars. Left out when that is 0.
dataCenterstringPublishing data center, the same id the providers input takes.
archiveCenter, organizationsstring, string[]The archiving organisation in its own spelling, and every organisation listed.
platformsstring[]Satellites, aircraft, buoys or models behind the dataset.
processingLevelstring0 … 4 or NA.
collectionDataTypestringScience quality, near-real-time or expedited, where stated.
consortiumsstring[]Programmes such as EOSDIS or GEOSS.
granuleCountintegerFiles the archive holds (with includeGranuleCounts).
cloudHostedbooleanThe dataset lives in cloud storage, so its files carry s3:// links.
ongoingbooleanTrue when the dataset has no end date — new files keep arriving.
doiUrl, documentationUrlsstring, string[]Citation DOI, user guides and algorithm documents.

Data-file rows (granules)

FieldTypeMeaning
producerGranuleIdstringThe file name the producing archive gave — what title carries.
granuleUrstringThe catalog's own title for the file; for some archives an internal id such as LAADS:10066693097.
collectionConceptId, datasetTitlestringThe dataset the file belongs to.
dayNightFlagstringDAY, NIGHT, BOTH or UNSPECIFIED.
granuleSizeMbnumberFile size in megabytes.
downloadUrlsstring[]HTTPS addresses of this file. Links of the whole dataset are never mixed in.
s3Urlsstring[]s3:// addresses, for a job in the archive's own AWS region.
opendapUrlstringOPeNDAP address, for reading a subset instead of the whole file.
browseUrls, metadataUrlsstring[]Preview images, and the metadata documents the catalog links for the file and for its archive.
needsEarthdataLoginbooleanA hint read from the URL path (-protected versus -public), not a guarantee.

Both modes: dataCenter, timeStart, timeEnd, boxes, polygons, points, coordinateSystem, onlineAccess, hasBrowse, originalFormat, revisionDate (when the catalog record was last revised, not when the data changed), source.

Marker rows. A short name or concept id the catalog does not know gets one row with rowType: "notFound", found: false, requested, requestedField and a note on what to do — instead of a silent empty result or a wider search. Such a row is written to the dataset, so it is billed like any other row.

With fields set, the row keeps only the columns you named, in that order, with the always-kept columns you did not name in front of them.

Dataset views: Datasets and files found (the overview table), Data files and their links, Place and period covered.

Use it from code / agents

curl -X POST "https://api.apify.com/v2/acts/yadroo~nasa-earthdata-search/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"mode":"collections","query":"wildfire","withGranulesOnly":true,"maxItems":20}'
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
// Step 1: find the datasets and keep their concept ids.
const found = await client.actor('yadroo/nasa-earthdata-search').call({ query: 'nighttime lights', withGranulesOnly: true, maxItems: 10 });
const datasets = (await client.dataset(found.defaultDatasetId).listItems()).items;
// Step 2: list the files of one of them.
const files = await client.actor('yadroo/nasa-earthdata-search').call({
mode: 'granules',
conceptIds: [datasets[0].conceptId],
temporalFrom: '2026-09-01',
maxItems: 50,
});
const { items } = await client.dataset(files.defaultDatasetId).listItems();
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("yadroo/nasa-earthdata-search").call(run_input={
"mode": "granules",
"shortNames": ["MOD11A1"],
"boundingBox": "70,40,80,50",
"temporalFrom": "2026-09-01",
"temporalTo": "2026-09-03",
"maxItems": 50,
})
items = client.dataset(run["defaultDatasetId"]).list_items().items

MCP: add https://mcp.apify.com to Claude / Cursor / any MCP client and call the yadroo/nasa-earthdata-search tool with the same JSON input.

The two-step pattern is the one worth knowing: a collections run answers "which dataset", a granules run answers "which files". Store the conceptId, not the short name — a concept id is permanent and never collides, while a short name can be re-versioned.

Pricing

Pay per event: $0.001 per run start + $0.002 per metadata row. A row is any row written to the dataset — a dataset row, a data-file row, or the found: false marker row of a short name or concept id the catalog does not know. There is no free tier of rows: every run pays the start event even if it returns nothing.

RunCost
The default run, 25 dataset rows$0.001 + 25 × $0.002 = $0.051
A file listing, 50 rows$0.001 + 50 × $0.002 = $0.101
A daily watch task that found 4 new files$0.001 + 4 × $0.002 = $0.009
The largest run the schema allows, 2000 rows$0.001 + 2000 × $0.002 = $4.001

maxItems is the real cost control: paging stops as soon as the cap is reached. On top of it, the run respects your Maximum cost per run: when the budget runs out the run stops, keeps every row you already paid for, and ends with "Stopped at your spending limit: N rows delivered". Apify's paid plans apply their usual discount to these prices.

Limits & FAQ

How fast is it? One request to the catalog returns up to 2000 records, so a normal run is one request. Measured in the Apify cloud on 2026-10-07: a 20–25-row run takes 3–10 seconds end to end including the container start, and the largest run the schema allows — 2000 data files of a daily product — took 31 seconds for all 2000 rows. That is about 4000 rows a minute, so nothing in this actor comes close to the default 900-second run timeout. The actor paces itself at one request per second per host regardless.

Does the source rate-limit? Yes, and it publishes no number: it throttles by request signature and answers HTTP 429 with a Retry-After header. The actor waits exactly that long and continues more slowly — a throttle is not a block. Because one request carries up to 2000 records, a normal run never comes close to the limit.

What if a run cannot finish? A run that nears its timeout stops starting new work, keeps every row already read, and ends successfully with "Stopped before the run timeout: N rows saved". Checked in the cloud on 2026-10-07: the same 2000-row input given only 30 seconds returned 1750 rows and that exact status instead of being killed. The spending limit works the same way — "Stopped at your spending limit: N rows delivered". You never lose rows you paid for.

How deep can a file listing go? An ungrouped file query in this catalog stops at its 10 000th match, and maxItems caps a single run at 2000 rows anyway. For more, split the job by time window or by area — the run says so in its status message when it hits the depth limit.

Why can I not search files by keyword? The catalog indexes free text over datasets only, not over single files. That is why granules mode needs shortNames or conceptIds: find the dataset first, then list its files.

Why is there no instrument column on a dataset row? The catalog's compact dataset record leaves the instrument list out. The instruments filter works (the source applies it); what you get back is the platforms column.

Why is the input called "data center" but sent as a provider? Because the catalog's own data_center parameter matches organisation names (PO.DAAC, NASA/GSFC/…), while the dataCenter column of a record holds the provider id (POCLOUD). Wiring the input to the parameter of the same name would return nothing — checked on 2026-10-07 — so the input sends provider, and filter and column always use the same words.

Do the download links work without an account? Many need a free Earthdata Login account; needsEarthdataLogin reads the archive's URL path and says true when they very likely do. It is a hint: the catalog publishes no per-file access flag. This actor never downloads a file, so no account is needed to run it.

Is there a "changed in the last N hours" filter? No, deliberately. The catalog's revision parameters are not something we verified, and filtering after the fetch would mean paying for rows that are then thrown away. Use the honest recipe instead: granules mode, one shortNames value, sort: newestData, onlyNew: true and a small maxItems, on a daily schedule. The memory is kept per actor or task, so two tasks watching two datasets never interfere.

A global dataset matches my small bounding box. Why? The spatial filter is overlap, not containment, and a global footprint overlaps everything. Combine it with processingLevels or providers to narrow the answer.

What is not included? The data files themselves, restricted metadata that needs an Earthdata Login token, and anything outside NASA's Common Metadata Repository. Individual international-partner datasets can carry their own use conditions on the files; those conditions are about the files, which this actor never touches.

An empty result versus an error. A filter the catalog simply has nothing for ends as a successful run with zero rows and a status message saying what was searched. A value the catalog does not know ends differently: a bad short name or concept id becomes a found: false row, and an unknown platform, instrument or data center stops the run with the closest known names — never a silently wider search.

Questions or problems: open an issue on the Issues tab of this actor.


Made by Yadroo. Sibling actors: nasa-eonet-events, nasa-asteroid-approaches, data-gov-datasets, open-meteo-weather, openalex-works.