Copy for LLM[View as Markdown](https://docs.planet.com/develop/apis/data/stac/) # STAC Support (Beta) info STAC support is currently in beta. Planet provides an experimental STAC service at . For details on the routes available, see the [API reference](https://api.planet.com/x/data/docs). The service also hosts a [generic STAC browser](https://api.planet.com/x/data/browse/) that can be used to view metadata on collections and items in the global catalog. ### Authentication As with other Planet APIs, the STAC services require authentication. Authentication options include: * basic auth with an API key in the username field *or* * a bearer token in an `Authorization` header. The links generated by the service (For example, to tiles for an item) will *not* include your credentials by default. For convenience, you can include the `?auth=true` query string to have the service generate links that include your credentials. Other services or systems that might share the generated metadata should not use this parameter. ### Planet Catalog The Planet STAC catalog uses the [Planet STAC Extension](https://github.com/planetlabs/stac-extension) to include fields and attributes specific to Planet products. To align with STAC conventions, some fields may be similar but not identical to the equivalent field in other Planet systems. To view the differences between fields in the STAC service and other Planet APIs, see [Planet STAC Extension field mapping and scope](https://github.com/planetlabs/stac-extension/blob/main/mapping.md). ### Item Queries The `items` endpoint for a feature collection accepts the following query parameters: * `limit` - Limit the number of items returned per page. By default, 100 items are returned per page. * `datetime` - Filter items based on acquisition time. For date range queries, provide a `/` delimited pair of formatted datetimes. For open ended ranges, use `..`. For example, to get images acquired in 2020 and later, make a query like `datetime=2020-01-01T00:00:00Z/..`. * `bbox` - Filter items based on a geographic bounding box. The `bbox` parameter is a list of min longitude, max longitude, min latitude, max latitude values separated by commas. * `auth` - Include credentials in resource links. By default, credentials are not included in links. See the [API reference](https://api.planet.com/x/data/docs#tag/Data/operation/ListItems) for more detail. ### Cross-Collection Search A basic temporal or spatial search can be performed using the item query parameters described above. The `/search` endpoint can be used instead to search using additional parameters or across multiple collections. A `POST` request to the `/search` endpoint initiates a search. The result of a search is an item collection (as returned by the `items` endpoint) with pagination links. When posting a search, the body of the request is a JSON object with the following properties: * `limit` - Limit the number of items returned. By default, 100 items are returned. * `collections` - A comma-delimited list of collection identifiers (or item types) to be used in the search. By default, all available collections will be searched. * `bbox` - Filter items based on a geographic bounding box. The `bbox` value is an array of min longitude, max longitude, min latitude, max latitude values. * `intersects` - Filter based on a GeoJSON geometry. The `intersects` value can be any GeoJSON geometry type. * `datetime` - Filter items based on acquisition time. For date range queries, provide a `/` delimited pair of formatted datetimes. For open ended ranges, use `..`. For example, to get images acquired in 2020 and later, include a `datetime` value like `"2020-01-01T00:00:00Z/.."`. * `ids` - Filter based on item identifiers as a list of strings. * `filter` - A filter using the JSON encoding of the [OGC Common Query Language](https://docs.ogc.org/is/21-065r2/21-065r2.html) (CQL2). The syntax supports spatial comparisons (For example, `s_intersects`), temporal comparisons (For example, `t_after`), numeric comparisons (For example, `>=`), logical expressions (For example, `or`), and additional comparison operators (For example, `in`). See below for example CQL2 searches and their Planet query equivalents. Searches posted to the `/search` endpoint can also use the `auth` query parameter as described above. #### Geometry intersection The request below is equivalent to a Data API search with a `GeometryFilter`. * CURL ``` curl --request POST \ -u "${PL_API_KEY}:" \ -H "Content-Type: application/json" \ --url "https://api.planet.com/x/data/search" \ -d \ '{ "limit": 10, "collections": ["PSScene", "SkySatScene"], "filter": { "op": "s_intersects", "args": [ {"property": "geometry"}, { "type": "Point", "coordinates": [-111, 45.68] } ] } }' ``` #### Date range The request below is equivalent to a Data API search with a `DateRangeFilter`. * CURL ``` curl --request POST \ -u "${PL_API_KEY}:" \ -H "Content-Type: application/json" \ --url "https://api.planet.com/x/data/search" \ -d \ '{ "limit": 10, "collections": ["PSScene", "SkySatScene"], "filter": { "op": "t_intersects", "args": [ {"property": "updated"}, {"interval": ["2020-01-01", "2021-01-01"]} ] } }' ``` #### Logical filters The request below is equivalent to a Data API search with an `AndFilter` that includes a `GeometryFilter`, a `DateRangeFilter`, and a filter for cloud cover. Logical operators `and`, `or`, and `not` are supported. * CURL ``` curl --request POST \ -u "${PL_API_KEY}:" \ -H "Content-Type: application/json" \ --url "https://api.planet.com/x/data/search" \ -d \ '{ "limit": 10, "collections": ["PSScene"], "filter": { "op": "and", "args": [ { "op": "s_intersects", "args": [ {"property": "geometry"}, { "type": "Point", "coordinates": [-111, 45.68] } ] }, { "op": "t_after", "args": [ {"property": "updated"}, {"date": "2024-07-01"} ] }, { "op": ">=", "args": [ {"property": "clear_percent"}, 50 ] } ] } }' ``` #### Comparison filters The `in` comparison operator can be used to search for items with a property value that matches a string or a number in a list. The request below is equivalent to a Data API search with a `NumberInFilter`. * CURL ``` curl --request POST \ -u "${PL_API_KEY}:" \ -H "Content-Type: application/json" \ --url "https://api.planet.com/x/data/search" \ -d \ '{ "limit": 10, "collections": ["PSScene"], "filter": { "op": "in", "args": [ {"property": "gsd"}, [3, 6, 9] ] } }' ``` The request below is equivalent to a Data API search with a `StringInFilter`. * CURL ``` curl --request POST \ -u "${PL_API_KEY}:" \ -H "Content-Type: application/json" \ --url "https://api.planet.com/x/data/search" \ -d \ '{ "limit": 10, "collections": ["PSScene"], "filter": { "op": "in", "args": [ {"property": "satellite_id"}, ["2414", "2415"] ] } }' ``` The `between` operator can compare a numeric property to a range of values. The request below is equivalent to a Data API search with a `RangeFilter`. * CURL ``` curl --request POST \ -u "${PL_API_KEY}:" \ -H "Content-Type: application/json" \ --url "https://api.planet.com/x/data/search" \ -d \ '{ "limit": 10, "collections": ["PSScene"], "filter": { "op": "between", "args": [ {"property": "gsd"}, 13, 15 ] } }' ``` The `<`, `<=`, `>`, and `>=` operators can also create range filters for numeric properties. The `=` and `<>` operators can filter based on a numeric or string property. Filters with the above comparison operators require a property expression as the first argument. #### Asset filter To filter for items that include a specific asset, use the `asset` function in a filter. The request below is equivalent to a Data API search with a `AssetFilter`. * CURL ``` curl --request POST \ -u "${PL_API_KEY}:" \ -H "Content-Type: application/json" \ --url "https://api.planet.com/x/data/search" \ -d \ '{ "limit": 10, "collections": ["PSScene"], "filter": { "op": "asset", "args": ["analytic"] } }' ``` #### Permission filter To filter for items for which the user has a specific permission, use the `permission` function in a filter. The request below is equivalent to a Data API search with a `PermissionFilter`. * CURL ``` curl --request POST \ -u "${PL_API_KEY}:" \ -H "Content-Type: application/json" \ --url "https://api.planet.com/x/data/search" \ -d \ '{ "limit": 10, "collections": ["PSScene"], "filter": { "op": "permission", "args": ["assets:download"] } }' ``` #### Update filter To filter for items with a specific property updated, use the `updated` function in a filter. The request below is equivalent to a Data API search with a `UpdateFilter`. * CURL ``` curl --request POST \ -u "${PL_API_KEY}:" \ -H "Content-Type: application/json" \ --url "https://api.planet.com/x/data/search" \ -d \ '{ "limit": 10, "collections": ["PSScene"], "filter": { "op": "updated", "args": [ {"property": "ground_control"}, ">", {"date": "2020-01-01"} ] } }' ``` ### PySTAC For Python scripts and applications, the [PySTAC client library](https://pystac-client.readthedocs.io/en/stable/index.html) can access the Planet STAC service. #### Configure the PySTAC client With the PySTAC client library installed, create a client for use with the Planet STAC service. * Python ``` import base64 import os from pystac_client import Client api_key = os.environ.get("PL_API_KEY") assert api_key is not None, "the PL_API_KEY environment variable must be set" # create a client using your API key userpass = f"{api_key}:" client = Client.open( url="https://api.planet.com/x/data/", headers={"Authorization": f"Basic {base64.b64encode(userpass.encode()).decode()}"}, ) ``` #### Set up logging (optional) Logging is optional but may be useful: * Python ``` import logging logging.basicConfig() logger = logging.getLogger("pystac_client") # optionally set to DEBUG to see API calls logger.setLevel(logging.INFO) ``` #### Search for images Use the PySTAC client to search for Planet data. In this example, we search for images that are at least 50% clear: * Python ``` params = dict( max_items=100, collections="PSScene", intersects={"type": "Point", "coordinates": [-111, 45.68]}, datetime="2024-06-01/2024-08-01", filter={"op": ">=", "args": [{"property": "clear_percent"}, 50]}, ) search = client.search(**params) # max of 100 items, get them all as a list items = list(search.items_as_dicts()) ``` #### Working with item properties Planet STAC items contain properties. The example below plots the values of `pl:clear_percent` using [matplotlib](https://matplotlib.org/). * Python ``` from datetime import datetime import matplotlib.pyplot as plt clear_percents = [] dates = [] for item in items: properties = item.get("properties", {}) clear_percents.append(properties.get("pl:clear_percent")) dates.append( datetime.strptime(properties.get("datetime"), "%Y-%m-%dT%H:%M:%S.%f%z") ) plt.xlabel("Date") plt.ylabel("Clear Percent") plt.xticks(rotation=30) plt.title("Two Months of Imagery") plt.plot(dates, clear_percents, marker="o", markerfacecolor="white", linewidth=0.5) ```