The Shutterstock API provides access to Shutterstock's library of media, as well as information about customers' accounts and the contributors that provide the media. It allows customer platforms to search for media, view information and previews for the media, and license and download media.

Authentication is required for all endpoints in the Shutterstock public API. The API accepts HTTP basic authentication for some endpoints and OAuth authentication for all endpoints. See Authentication.

Basic requests

After you have authenticated to the API, you can send requests to the API using any programming language or program that can send HTTP requests. The base URL for all endpoints is https://api.shutterstock.com. Here are some examples:

cURL:

curl -X GET "https://api.shutterstock.com/v2/images/search" \
--header "Authorization: Bearer $SHUTTERSTOCK_API_TOKEN" \
-G \
--data-urlencode "query=hiking" \
--data-urlencode "image_type=photo" \
--data-urlencode "orientation=vertical" \
--data-urlencode "people_number=3"

PHP:

$queryFields = [
  "query" => "hiking",
  "image_type" => "photo",
  "orientation" => "vertical",
  "people_number" => 3
];

$options = [
  CURLOPT_URL => "https://api.shutterstock.com/v2/images/search?" . http_build_query($queryFields),
  CURLOPT_USERAGENT => "php/curl",
  CURLOPT_HTTPHEADER => [
    "Authorization: Bearer $SHUTTERSTOCK_API_TOKEN"
  ],
  CURLOPT_RETURNTRANSFER => 1
];

$handle = curl_init();
curl_setopt_array($handle, $options);
$response = curl_exec($handle);
curl_close($handle);

$decodedResponse = json_decode($response);
print_r($decodedResponse);

JavaScript:

const request = require("request-promise");

request.get("https://api.shutterstock.com/v2/images/search", {
  json: true,
  headers: {
    "User-Agent": "request",
    "Authorization": "Bearer " + process.env.SHUTTERSTOCK_API_TOKEN
  },
  qs: {
    "query": "hiking",
    "image_type": "photo",
    "orientation": "vertical",
    "people_number": 3
  },
  useQueryString: true
})
.then(res => {
  console.log(res);
});

Passing multiple values

Some parameters can accept more than one value. In this case, you can specify the same parameter more than one time, as in the following examples. For example, the endpoint DELETE /v2/images/collections/{id}/items removes one or more images from a collection. You can specify the item_id query parameter multiple times to delete more than one image.

Depending on the programming language, sometimes you repeat the parameter, as in item_id=721943485&item_id=776540. In other languages, you create an array with multiple values. In most cases, you can't combine the items into a single value, as in item_id=721943485, 776540. One exception is the query parameter on the search endpoints, which can accept a search string of multiple keywords, such as query=dogs park sun.

You can tell which parameters accept multiple values by looking in the API reference. Parameters that can accept multiple values have a type of "array[{type}]," such as "array[string]." Some endpoints handle the multiple values with an AND condition and others with an OR condition.

cURL:

curl -X DELETE "https://api.shutterstock.com/v2/images/collections/97531/items" \
-H "Authorization: Bearer $SHUTTERSTOCK_API_TOKEN" \
-G \
--data-urlencode "item_id=721943485" \
--data-urlencode "item_id=776540"

PHP:

$body = [
  "item_id" => [
    "721943485",
    "776540"
  ]
];
$encodedBody = json_encode($body);

$options = [
  CURLOPT_URL => "https://api.shutterstock.com/v2/images/collections/97531/items",
  CURLOPT_CUSTOMREQUEST => "DELETE",
  CURLOPT_POSTFIELDS => $encodedBody,
  CURLOPT_USERAGENT => "php/curl",
  CURLOPT_HTTPHEADER => [
    "Authorization: Bearer $SHUTTERSTOCK_API_TOKEN"
  ],
  CURLOPT_RETURNTRANSFER => 1
];

$handle = curl_init();
curl_setopt_array($handle, $options);
$response = curl_exec($handle);
curl_close($handle);

$decodedResponse = json_decode($response);
print_r($decodedResponse);

JavaScript:

const request = require("request-promise");

request.delete("https://api.shutterstock.com/v2/images/collections/97531/items", {
  json: true,
  headers: {
    "User-Agent": "request",
    "Authorization": "Bearer " + process.env.SHUTTERSTOCK_API_TOKEN
  },
  qs: {
    "item_id": ["721943485", "776540"]
  },
  useQueryString: true
});

Responses

The API returns information in JSON format. Most programming languages have libraries that can accept and manipulate JSON data. In most cases, the metadata is in the root fields of the JSON data, and the data about the media is in a data field.

For example, search results include the paging information, the total number of results, and a unique identifier for the search, as in the following example. You can use the paging information to retrieve results in parts, as described in Paging responses. You can submit the search identifier when you license media to improve search rankings.

Response examples

The following JSON code is the response to a search request. The metadata shows that the response is showing the first page of three results, of a total of 1,070 results.

The data field is an array of the results themselves. Each search result includes the ID of the piece of media. In the case of these image results, the response shows information about the image, such as its aspect ratio, its dimensions, the media type (image, in this case, as opposed to video or audio search results), the type of image (such as photo, vector, or illustration), the contributor that provided the image, and a textual description for the image. Each search result includes one or more preview links that you can use to preview the media before licensing and downloading the full version.

Searches for different types of media return different information. For example, video search results include the duration of the video in seconds and the aspect ratio expressed both as a ratio and as a decimal. Audio search results include the file size in bytes and the title for the track.

{
  "page": 1,
  "per_page": 1,
  "total_count": 1070,
  "search_id": "rTBCE8T2weANh6pK85Fdvw",
  "data": [
    {
      "id": "1105302317",
      "aspect": 0.6667,
      "assets": {
        "preview": {
          "height": 450,
          "url": "https://image.shutterstock.com/display_pic_with_logo/3265442/1105302317/stock-photo-a-woman-with-children-goes-hiking-the-woman-took-her-sons-by-the-arms-the-family-goes-on-a-dirt-1105302317.jpg",
          "width": 300
        },
        "small_thumb": {
          "height": 100,
          "url": "https://thumb7.shutterstock.com/thumb_small/3265442/1105302317/stock-photo-a-woman-with-children-goes-hiking-the-woman-took-her-sons-by-the-arms-the-family-goes-on-a-dirt-1105302317.jpg",
          "width": 67
        },
        "large_thumb": {
          "height": 150,
          "url": "https://thumb7.shutterstock.com/thumb_large/3265442/1105302317/stock-photo-a-woman-with-children-goes-hiking-the-woman-took-her-sons-by-the-arms-the-family-goes-on-a-dirt-1105302317.jpg",
          "width": 100
        },
        "huge_thumb": {
          "height": 260,
          "url": "https://image.shutterstock.com/image-photo/woman-children-goes-hiking-took-260nw-1105302317.jpg",
          "width": 173
        }
      },
      "contributor": {
        "id": "3265442"
      },
      "description": "A woman with children goes hiking. The woman took her sons by the arms. The family goes on a dirt road. The boy walks with his brother and mother in the forest. Hike with backpacks. Fisheye lens",
      "image_type": "photo",
      "media_type": "image"
    }
  ],
  "spellcheck_info": {}
}

Requests to different endpoints return different data. For example, sending a request to GET /v2/images/collections returns a list of collections that belong to the token user. Each item in the data field provides information about a collection, including its ID, name, number of items, and when it was updated.

{
    "data": [
        {
            "id": "92762295",
            "name": "My collection of sunset pictures",
            "total_item_count": 7,
            "items_updated_time": "2018-06-26T17:07:01-04:00",
            "cover_item": {
                "id": "35940817"
            }
        },
        {
            "id": "64602180",
            "name": "My collection of mountain pictures",
            "total_item_count": 6,
            "items_updated_time": "2018-04-20T16:26:28-04:00",
            "cover_item": {
                "id": "269253157"
            }
        }
    ]
}

Sending a request to GET /v2/images/collections/{id}/items returns information about the images in the collection, including the ID and the time each was added to the collection:

{
    "data": [
        {
            "id": "757853977",
            "added_time": "2018-09-17T14:17:38-04:00"
        },
        {
            "id": "309705941",
            "added_time": "2018-09-17T14:17:34-04:00"
        },
        {
            "id": "721943485",
            "added_time": "2018-09-17T14:17:30-04:00"
        }
    ]
}

Paging responses

Many endpoints, including search endpoints, split long response data into multiple pages with the page and per_page parameters. For example, if a search result has 20 pieces of media, you can retrieve items 6-10 by using page=2 and per_page=5 in the request, as shown in these examples:

cURL:

curl -X GET "https://api.shutterstock.com/v2/images/search" \
--header "Authorization: Bearer $SHUTTERSTOCK_API_TOKEN" \
-G \
--data-urlencode "query=giraffes" \
--data-urlencode "page=2" \
--data-urlencode "per_page=5"

PHP:

$queryFields = [
  "query" => "giraffes",
  "page" => 2,
  "per_page" => 5
];

$options = [
  CURLOPT_URL => "https://api.shutterstock.com/v2/images/search?" . http_build_query($queryFields),
  CURLOPT_USERAGENT => "php/curl",
  CURLOPT_HTTPHEADER => [
    "Authorization: Bearer $SHUTTERSTOCK_API_TOKEN"
  ],
  CURLOPT_RETURNTRANSFER => 1
];

$handle = curl_init();
curl_setopt_array($handle, $options);
$response = curl_exec($handle);
curl_close($handle);

$decodedResponse = json_decode($response);
print_r($decodedResponse);

JavaScript:

const request = require("request-promise");

request.get("https://api.shutterstock.com/v2/images/search", {
  json: true,
  headers: {
    "User-Agent": "request",
    "Authorization": "Bearer " + process.env.SHUTTERSTOCK_API_TOKEN
  },
  qs: {
    "query": "giraffes",
    "page": 2,
    "per_page": 5
  },
  useQueryString: true
})
.then(res => {
  console.log(res);
});

Sorting results

The sort parameter controls how results are ordered. By default, image and video searches return the most popular media first, and audio searches return the tracks that best match the overall search criteria first.

The image and video search endpoints can order results in the following ways:

  • "newest": Sort by when the image was added.
  • "popular": Sort by the popularity of the image.
  • "random": Return the search results in random order.
  • "relevance": Sort by how well the result matches the overall search criteria.

The audio search endpoint can sort results in the following ways:

  • "artist": Sort by the artist name.
  • "bpm": Sort by beats per minute.
  • "duration": Sort by the length of the track.
  • "freshness": Sort by when the track was added.
  • "ranking_all": Sort by aggregated factors including popularity, keywords, and views.
  • "score": Sort by the relevancy score based on the search query.
  • "title": Sort alphabetically by title.

For audio only, you can use the sort_order parameter to return results in ascending ("asc") or descending ("desc," the default) order.

Here are some examples:

cURL:

curl -X GET "https://api.shutterstock.com/v2/videos/search" \
--header "Authorization: Bearer $SHUTTERSTOCK_API_TOKEN" \
-G \
--data-urlencode "query=boats" \
--data-urlencode "sort=popular"


curl -X GET "https://api.shutterstock.com/v2/audio/search" \
--header "Authorization: Bearer $SHUTTERSTOCK_API_TOKEN" \
-G \
--data-urlencode "instruments=Piano" \
--data-urlencode "duration_from=300"
--data-urlencode "sort=bpm" \
--data-urlencode "sort_order=desc"

PHP:

$videoQueryFields = [
  "query" => "boats",
  "sort" => "popular"
];

$videoOptions = [
  CURLOPT_URL => "https://api.shutterstock.com/v2/videos/search?" . http_build_query($videoQueryFields),
  CURLOPT_USERAGENT => "php/curl",
  CURLOPT_HTTPHEADER => [
    "Authorization: Bearer $SHUTTERSTOCK_API_TOKEN"
  ],
  CURLOPT_RETURNTRANSFER => 1
];

$videoHandle = curl_init();
curl_setopt_array($videoHandle, $videoOptions);
$videoResponse = curl_exec($videoHandle);
curl_close($videoHandle);

$videoDecodedResponse = json_decode($videoResponse);
print_r($videoDecodedResponse);


$audioQueryFields = [
  "query" => "Piano",
  "duration_from" => 300,
  "sort" => "bpm",
  "sort_order" => "desc"
];

$audioOptions = [
  CURLOPT_URL => "https://api.shutterstock.com/v2/audio/search?" . http_build_query($audioQueryFields),
  CURLOPT_USERAGENT => "php/curl",
  CURLOPT_HTTPHEADER => [
    "Authorization: Bearer $SHUTTERSTOCK_API_TOKEN"
  ],
  CURLOPT_RETURNTRANSFER => 1
];

$audioHandle = curl_init();
curl_setopt_array($audioHandle, $audioOptions);
$audioResponse = curl_exec($audioHandle);
curl_close($audioHandle);

$audioDecodedResponse = json_decode($audioResponse);
print_r($audioDecodedResponse);

JavaScript:

const request = require("request-promise");

request.get("https://api.shutterstock.com/v2/videos/search", {
  json: true,
  headers: {
    "User-Agent": "request",
    "Authorization": "Bearer " + process.env.SHUTTERSTOCK_API_TOKEN
  },
  qs: {
    "query": "boats",
    "sort": "popular",
    "sort_order": "asc"
  },
  useQueryString: true
})
.then(res => {
  console.log(res);
});


request.get("https://api.shutterstock.com/v2/audio/search", {
  json: true,
  headers: {
    "User-Agent": "request",
    "Authorization": "Bearer " + process.env.SHUTTERSTOCK_API_TOKEN
  },
  qs: {
    "query": "Piano",
    "duration_from": 300,
    "sort": "bpm",
    "sort_order": "desc"
  },
  useQueryString: true
})
.then(res => {
  console.log(res);
});

Full view and minimal view

The view parameter on some search and informational endpoints controls how much detail is shown in the response. By default (view=minimal), the response includes a moderate amount of detail about each search result, but if you set the view parameter to full, the response includes complete information about each result. For example, full image results include the full list of keywords and categories that apply to each image.

Here are examples of requesting full results:

cURL:

curl -X GET "https://api.shutterstock.com/v2/images/search" \
--header "Authorization: Bearer $SHUTTERSTOCK_API_TOKEN" \
-G \
--data-urlencode "query=airplane" \
--data-urlencode "view=full"

PHP:

$queryFields = [
  "query" => "airplane",
  "view" => "full"
];

$options = [
  CURLOPT_URL => "https://api.shutterstock.com/v2/images/search?" . http_build_query($queryFields),
  CURLOPT_USERAGENT => "php/curl",
  CURLOPT_HTTPHEADER => [
    "Authorization: Bearer $SHUTTERSTOCK_API_TOKEN"
  ],
  CURLOPT_RETURNTRANSFER => 1
];

$handle = curl_init();
curl_setopt_array($handle, $options);
$response = curl_exec($handle);
curl_close($handle);

$decodedResponse = json_decode($response);
print_r($decodedResponse);

JavaScript:

const request = require("request-promise");

request.get("https://api.shutterstock.com/v2/images/search", {
  json: true,
  headers: {
    "User-Agent": "request",
    "Authorization": "Bearer " + process.env.SHUTTERSTOCK_API_TOKEN
  },
  qs: {
    "query": "airplane",
    "view": "full",
  },
  useQueryString: true
})
.then(res => {
  console.log(res);
});

For examples of the results, see Results.

Showing only specific fields

You can limit the information shown further with the fields parameter. You pass one or more fields and the API returns only those fields. The following examples perform an image search and return only the ID of the image and a link to a preview image. The value of the fields parameter specifies fields in the same way that Google supports it across many of their APIs. For more information, see Partial responses in the Google API documentation.

To specify the fields to return, use slashes to indicate the position of the field in the hierarchy of the normal JSON response. In the following example, the string fields=data(id,assets/preview/url) returns the data.id field and the data.assets.preview.url field.

cURL:

curl -X GET "https://api.shutterstock.com/v2/images/search" \
-H "Authorization: Bearer $SHUTTERSTOCK_API_TOKEN" \
-G \
--data-urlencode "query=dolphins" \
--data-urlencode "fields=data(id,assets/preview/url)"

PHP:

$queryFields = [
  "query" => "kites",
  "fields" => "fields=data(id,assets/preview/url)"
];

$options = [
  CURLOPT_URL => "https://api.shutterstock.com/v2/images/search?" . http_build_query($queryFields),
  CURLOPT_USERAGENT => "php/curl",
  CURLOPT_HTTPHEADER => [
    "Authorization: Bearer $SHUTTERSTOCK_API_TOKEN"
  ],
  CURLOPT_RETURNTRANSFER => 1
];

$handle = curl_init();
curl_setopt_array($handle, $options);
$response = curl_exec($handle);
curl_close($handle);

$decodedResponse = json_decode($response);
print_r($decodedResponse);

JavaScript:

const request = require("request-promise");

request.get("https://api.shutterstock.com/v2/images/search", {
  json: true,
  headers: {
    "User-Agent": "request",
    "Authorization": "Bearer " + process.env.SHUTTERSTOCK_API_TOKEN
  },
  qs: {
    "query": "kites",
    "fields": "fields=data(id,assets/preview/url)"
  },
  useQueryString: true
})
.then(res => {
  console.log(res);
});

The response shows only the specified fields:

{
  "data": [
    {
      "id": "547308685",
      "assets": {
        "preview": {
          "url": "https://image.shutterstock.com/display_pic_with_logo/567127/547308685/stock-photo-dolphin-547308685.jpg"
        }
      }
    },
    {
      "id": "794200186",
      "assets": {
        "preview": {
          "url": "https://image.shutterstock.com/display_pic_with_logo/1758188/794200186/stock-vector-silhouettes-of-dolphins-set-vector-illustration-794200186.jpg"
        }
      }
    },
    {
      "id": "388057081",
      "assets": {
        "preview": {
          "url": "https://image.shutterstock.com/display_pic_with_logo/324673/388057081/stock-photo-three-beautiful-dolphins-jumping-over-breaking-waves-hawaii-pacific-ocean-wildlife-scenery-marine-388057081.jpg"
        }
      }
    }
  ]
}

Rate limits

All applications are limited to a certain number of API requests per second. If your application exceeds its limit, the API returns an error response with a status code of 429. To request a higher rate limit, please contact us.