Log inSuggest an edit

Searching for imagery

This tutorial will walk you through how to search for imagery using the Planet Data API.

This guide is all about image metadata. When you're done, see step 2 to learn how to start downloading the image files. Step 2: Downloading imagery

If you haven't already, see the introduction for info on how to acquire an API key and setup your development environment. jq is a necessary tool for these examples.

ItemTypes

The Planet API brings together different classes of imagery, some classes represent different satellites, some represent different formats, sometimes it's both. Each class of imagery is identified by its "ItemType".

Examples of ItemTypes are

  • "PSOrthoTile" - Images taken by PlanetScope satellites in the OrthoTile format.
  • "REOrthoTile" - Images taken by RapidEye satellites in the OrthoTile format.

We can see what ItemTypes are avaliable to our API key with our first API query

➜  curl -L -H "Authorization: api-key $PL_API_KEY" \
    'https://api.planet.com/data/v1/item-types' | jq '.item_types[].id'
"REOrthoTile"
"PSOrthoTile"

Select an Area of Interest (AOI)

You can use geojson.io to get geometry coordinates for an area that interests you, start small : )

Here's an AOI around a Reservoir near Redding California

The highlighted JSON is a GeoJSON geometry object that we can use as a filter in the Planet API.

Filters

Several Planet API endpoints operate on filters, which can be used to narrow down imagery by a variety of attributes like location, cloud coverage %, acquisition date etc.

At this point, it will be easier if we start using Python to interact with the API. The runnable source file for all code snippets will be linked above each snippet.

Let's define some filters

examples/demo_filters.py

# the geo json geometry object we got from geojson.io
geo_json_geometry = {
  "type": "Polygon",
  "coordinates": [
    [
      [
        -122.52227783203125,
        40.660847697284815
      ],
      [
        -122.52227783203125,
        40.987154933797335
      ],
      [
        -122.01690673828124,
        40.987154933797335
      ],
      [
        -122.01690673828124,
        40.660847697284815
      ],
      [
        -122.52227783203125,
        40.660847697284815
      ]
    ]
  ]
}

# filter for items the overlap with our chosen geometry
geometry_filter = {
  "type": "GeometryFilter",
  "field_name": "geometry",
  "config": geo_json_geometry
}

# filter images acquired in a certain date range
date_range_filter = {
  "type": "DateRangeFilter",
  "field_name": "acquired",
  "config": {
    "gte": "2016-07-01T00:00:00.000Z",
    "lte": "2016-08-01T00:00:00.000Z"
  }
}

# filter any images which are more than 50% clouds
cloud_cover_filter = {
  "type": "RangeFilter",
  "field_name": "cloud_cover",
  "config": {
    "lte": 0.5
  }
}

# create a filter that combines our geo and date filters
# could also use an "OrFilter"
redding_reservoir = {
  "type": "AndFilter",
  "config": [geometry_filter, date_range_filter, cloud_cover_filter]
}

Stats Endpoint

A good first step would be to use our filter to query the stats endpoint, this will give us a date bucketed histogram to show us how many items match our filter

examples/stats_endpoint.py

import os
import requests
from requests.auth import HTTPBasicAuth

# our demo filter that filters by geometry, date and cloud cover
from demo_filters import redding_reservoir

# Stats API request object
stats_endpoint_request = {
  "interval": "day",
  "item_types": ["REOrthoTile"],
  "filter": redding_reservoir
}

# fire off the POST request
result = \
  requests.post(
    'https://api.planet.com/data/v1/stats',
    auth=HTTPBasicAuth(os.environ['PL_API_KEY'], ''),
    json=stats_endpoint_request)

print result.text

Run the script:

➜ python examples/stats_endpoint.py | jq
{
  "utc_offset": "+0h",
  "interval": "day",
  "buckets": [
    {
      "count": 6,
      "start_time": "2016-07-07T00:00:00.000000Z"
    },
    {
      "count": 9,
      "start_time": "2016-07-13T00:00:00.000000Z"
    },
    {
      "count": 3,
      "start_time": "2016-07-17T00:00:00.000000Z"
    },
    {
      "count": 6,
      "start_time": "2016-07-19T00:00:00.000000Z"
    },
    {
      "count": 6,
      "start_time": "2016-07-22T00:00:00.000000Z"
    }
  ]
}

Nice! We can see that in July 2016, RapidEye satellites imaged the area on 5 different days.

Search Endpoint

Now let's do a search, this takes the same filter object as the stats endpoint but returns complete metadata objects about the matching items.

examples/search_endpoint.py

import os
import requests
from requests.auth import HTTPBasicAuth

# our demo filter that filters by geometry, date and cloud cover
from demo_filters import redding_reservoir

# Search API request object
search_endpoint_request = {
  "item_types": ["REOrthoTile"],
  "filter": redding_reservoir
}

result = \
  requests.post(
    'https://api.planet.com/data/v1/quick-search',
    auth=HTTPBasicAuth(os.environ['PL_API_KEY'], ''),
    json=search_endpoint_request)

print result.text

You can use jq to filter the search response down to only item ids

➜  python examples/search_endpoint.py | jq '.features[].id'
"20160707_195147_1057916_RapidEye-1"
"20160707_195146_1057917_RapidEye-1"
"20160707_195150_1057817_RapidEye-1"
"20160707_195143_1058017_RapidEye-1"
"20160707_195143_1058016_RapidEye-1"
"20160707_195150_1057816_RapidEye-1"
"20160722_194931_1057916_RapidEye-2"
"20160722_194930_1057917_RapidEye-2"
"20160722_194928_1058016_RapidEye-2"
"20160722_194927_1058017_RapidEye-2"
...

With some more jq magic, we can grab the 3rd item from our search and display its properties. All of these values can be used in a search filter.

➜  python examples/search_endpoint.py | jq '.features[3].properties'
{
  "acquired": "2016-07-07T19:51:47Z",
  "anomalous_pixels": 0.05,
  "black_fill": 0,
  "cloud_cover": 0.05,
  "columns": 5000,
  "epsg_code": 32610,
  "grid_cell": "1057916",
  "gsd": 6.5,
  "item_type": "REOrthoTile",
  "origin_x": 523500,
  "origin_y": 4536500,
  "pixel_resolution": 5,
  "provider": "rapideye",
  "published": "2016-08-18T21:26:07Z",
  "rows": 5000,
  "satellite_id": "RapidEye-1",
  "sun_azimuth": 162.95195,
  "sun_elevation": 71.12186,
  "updated": "2016-08-29T04:50:33Z",
  "usable_data": 0.95,
  "view_angle": -13.04192
}

One Weird Trick

A cli exists to easily send GeoJson geometries to geojson.io

You can use jq to extract the geometry coordinates of a specific item from the search results and pipe it into the geojsonio tool

python examples/search_endpoint.py | jq '.features[3].geometry' | geojsonio

This visualizes the footprint of the 3rd item in the search

Next section: Downloading imagery