# iStock Scraper (`deadmist/istock-scraper`) Actor

Scrape iStock search results and contributor portfolios: titles, contributors, collections, upload dates and every asset keyword. A niche report per query shows supply, competition and the top keywords. Pay per asset.

- **URL**: https://apify.com/deadmist/istock-scraper.md
- **Developed by:** [Vladyslav Kosenko](https://apify.com/deadmist) (community)
- **Categories:** E-commerce, SEO tools
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## iStock Scraper

Scrape **iStock search results and contributor portfolios** without logging in. For each asset you get the **title, caption, contributor, collection (Main, Signature, Signature+), upload date, orientation, preview**, and optionally **the full keyword list**. Use it for microstock keyword research, competitor portfolio analysis, trend spotting and mood boards.

Each query or portfolio also produces a **niche report**: total results, the share of assets uploaded in the last 12 months, Signature share, top contributors, top keywords and iStock's related searches. In one table you can see whether a niche is saturated or still open.

You pay per asset. Proxies are included.

### Features

- **Any source:** keyword search, contributor portfolios, or any iStock search, portfolio or asset URL with its filters.
- **Every media type:** photos, illustrations, vectors and videos (with clip length and 4K/HD).
- **Sort like buyers do:** best match, **most popular** (iStock's ranking by sales and engagement) or newest.
- **Filters:** orientation and number of people.
- **Keywords and details:** the asset's full keyword list, main keyword, themes, location, release type, exclusivity and maximum resolution.
- **Niche report:** one summary row per query, so you can compare dozens of keywords at once.
- **Reliable:** blocked requests are retried with fresh proxy sessions, and residential IPs take over automatically.

### Use cases

- **Microstock keyword research:** find topics where buyers pick recent uploads (a high "new in the last 12 months" share means the niche is still open).
- **Better keywording:** copy the keyword structure of top-selling assets for your own uploads.
- **Competitor analysis:** track a contributor's portfolio size, best sellers and newest uploads.
- **Trend monitoring:** schedule a run with `sort: newest` and see what is being uploaded.
- **Creative research:** collect previews and titles for a mood board.

### Input example

```json
{
  "searchQueries": ["remote work", "christmas background", "ai technology"],
  "mediaType": "photography",
  "sort": "mostpopular",
  "maxItemsPerSource": 120,
  "includeKeywords": true,
  "nicheReport": true
}
```

### Output example

An asset:

```json
{
  "type": "asset",
  "query": "sunset",
  "position": 1,
  "totalResults": 7507024,
  "assetId": "1703754111",
  "url": "https://www.istockphoto.com/en/photo/sunset-dramatic-sky-clouds-gm1703754111-538988459",
  "title": "Sunset dramatic sky clouds",
  "caption": "Cloudscape and dramatic orange sky, sunset shot",
  "contributor": "valio84sl",
  "assetType": "image",
  "mediaType": "photography",
  "collection": "Main",
  "isSignature": false,
  "orientation": "Horizontal",
  "dateSubmitted": "2023-09-27T22:44:35Z",
  "thumbnailUrl": "https://media.istockphoto.com/id/1703754111/photo/sunset-dramatic-sky-clouds.jpg?s=170x170…",
  "keywords": ["Sunset", "Sky", "Cloud - Sky", "Dusk", "Cloudscape", "…"],
  "mainKeyword": "Sunset",
  "themes": ["Nature and landscape", "Spring", "Autumn"],
  "location": "Bulgaria",
  "releaseType": "no_release_required",
  "maxDimensions": { "width": 8192, "height": 5464 },
  "megapixels": "44.8 MP"
}
```

A niche report:

```json
{
  "type": "niche-report",
  "query": "sunset",
  "sort": "mostpopular",
  "totalResults": 7507024,
  "sampledAssets": 120,
  "newLast12MonthsPercent": 1.4,
  "signaturePercent": 27.1,
  "uniqueContributors": 52,
  "topContributors": [{ "contributor": "valio84sl", "assets": 8 }],
  "topKeywords": [{ "keyword": "Sky", "assets": 67 }],
  "relatedSearches": ["sunset sky", "sunrise", "ocean sunset", "beach sunset"]
}
```

Rows have a `type` field (`asset`, `niche-report` or `error`), so you can filter them in the dataset or via the API.

### Pricing

| Event | Price |
| --- | --- |
| Asset | $0.0008 |
| Keywords and details (only with *Include keywords*) | $0.0015 per asset |
| Niche report | $0.003 per query or portfolio |

1,000 assets cost $0.80, or $2.30 with keywords. A failed request is not charged.

### Tips

- iStock shows at most 6,000 assets (100 pages) per search. Split broad topics into narrower queries.
- `sort: mostpopular` with 100–200 assets per query gives a good niche report at low cost.
- For a contributor, combine the portfolio with `sort: newest` to see what they upload lately.

### FAQ

**Do I need an iStock account?** No. The actor reads public pages only.

**Does it return download counts?** No. iStock does not publish them. Use the *most popular* rank (`position`) as the demand signal.

**Is it legal?** The actor collects publicly available data. You are responsible for how you use it. Previews are watermarked and copyrighted by their owners.

# Actor input Schema

## `searchQueries` (type: `array`):

Keywords or phrases, the same as the iStock search box.

## `contributors` (type: `array`):

iStock contributor usernames or portfolio URLs, e.g. valio84sl or https://www.istockphoto.com/portfolio/valio84sl.

## `startUrls` (type: `array`):

Any iStock search, portfolio or asset page, with its filters. Asset pages always come with keywords.

## `mediaType` (type: `string`):

Applies to search queries and portfolios.

## `sort` (type: `string`):

Most popular is iStock's own ranking by sales and engagement, the best proxy for what buyers pick.

## `orientation` (type: `string`):

Applies to search queries and portfolios.

## `numberOfPeople` (type: `string`):

Applies to search queries and portfolios. Useful for finding "no people" backgrounds.

## `maxItemsPerSource` (type: `integer`):

iStock shows up to 100 pages of 60 assets per search.

## `includeKeywords` (type: `boolean`):

Opens each asset page for its full keyword list, main keyword, themes, location, release type, exclusivity and maximum resolution. Charged as an extra event per asset.

## `nicheReport` (type: `boolean`):

Adds one summary row per query or portfolio: total results, share of assets uploaded in the last 12 months, Signature share, top contributors, top keywords and related searches.

## `maxConcurrency` (type: `integer`):

How many queries, portfolios or URLs run at the same time.

## `maxAttempts` (type: `integer`):

Retries with a fresh proxy session before a request is given up.

## `proxyConfiguration` (type: `object`):

Apify Proxy is included in the price.

## Actor input object example

```json
{
  "searchQueries": [
    "sunset",
    "remote work",
    "christmas background"
  ],
  "contributors": [
    "valio84sl"
  ],
  "startUrls": [
    "https://www.istockphoto.com/search/2/image?phrase=coffee&orientations=vertical"
  ],
  "mediaType": "all",
  "sort": "best",
  "orientation": "any",
  "numberOfPeople": "any",
  "maxItemsPerSource": 100,
  "includeKeywords": false,
  "nicheReport": true,
  "maxConcurrency": 3,
  "maxAttempts": 6,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Assets and niche reports.

## `overview` (type: `string`):

The overview view of the dataset.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchQueries": [
        "sunset"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("deadmist/istock-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchQueries": ["sunset"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("deadmist/istock-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchQueries": [
    "sunset"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call deadmist/istock-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,deadmist/istock-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/QRhZcBfriCPvrbckM/builds/Q3htMeACa1U5XRT59/openapi.json
