# Pexels Scraper - Free Stock Photos & Videos, No API Key (`scrapewise/pexels-scraper`) Actor

Scrape Pexels photos and videos by keyword, photographer profile, collection or link, without an API key. Get title, alt text, tags, size, average color, photographer, image URLs in 8 sizes, video files, duration, views, downloads and likes. Error rows are free.

- **URL**: https://apify.com/scrapewise/pexels-scraper.md
- **Developed by:** [Scrapewise Data](https://apify.com/scrapewise) (community)
- **Categories:** AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.47 / 1,000 photo or video delivereds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Pexels Scraper: free stock photos and videos with tags, sizes, photographers and stats, no API key

Pexels Scraper collects **photos and videos from Pexels** by keyword, photographer profile, collection or direct link,
without a Pexels API key, an account or a browser. Each photo or video comes back as one clean row: title, alt text,
description, tags, width, height, average color and color palette, the photographer's public name and profile link,
image links in 8 ready-made sizes, and for videos the duration, frame rate, preview, thumbnails and every MP4 file
with its resolution. Turn on one checkbox to also get views, downloads, likes and the camera data (EXIF) of each photo.

It is used to build image and video datasets for AI training and computer vision, to fill blogs, landing pages and
social posts with royalty-free media and the right attribution, to research which visual styles and topics get the
most downloads, and to follow what a photographer or a collection publishes over time.

### At a glance

| What | Price |
|---|---|
| Photo or video delivered | **US$ 2.90 per 1,000 items** on the Free plan (US$ 0.0029 each) |
| Paid Apify plans | Bronze US$ 2.76, Silver US$ 2.61, Gold and above US$ 2.47 per 1,000 |
| Run start | US$ 0.005 per run |

- 3 searches with 30 photos each = 90 items = **US$ 0.27** on the Free plan.
- Views, downloads, likes and camera data cost nothing extra: same price per item.
- Error rows and duplicates are never charged. `maxItems` is a hard cap, and a spending limit set on the run stops it
  cleanly with everything delivered so far.
- No monthly fee and no API key to manage.

### Quick start

Photos for one keyword:

```json
{
  "searchQueries": ["ocean"],
  "maxResultsPerSearch": 30
}
```

Vertical 4K videos shorter than 30 seconds, for reels and stories:

```json
{
  "searchQueries": ["city night", "coffee shop"],
  "mediaType": "videos",
  "orientation": "portrait",
  "size": "large",
  "maxDuration": 30,
  "maxResultsPerSearch": 50
}
```

Everything a photographer published, with views, downloads and likes:

```json
{
  "startUrls": ["https://www.pexels.com/@ben-mack/"],
  "maxResultsPerSearch": 0,
  "includeDetails": true
}
```

You can also paste a Pexels search link exactly as it appears in your browser, filters included, such as
`https://www.pexels.com/search/videos/mountain/?orientation=portrait`. Links with a language prefix
(`/de-de/`, `/es-es/`, `/pt-br/`) work too.

### Input

| Field | What it does |
|---|---|
| `searchQueries` | Keywords, one per line. Each term is one Pexels search. |
| `mediaType` | `photos` (default) or `videos` for the search terms. |
| `startUrls` | Pexels links: search pages, photographer profiles (`/@username/`), collections, single photo or video pages. |
| `maxResultsPerSearch` | Items per search term or link, in Pexels order (default 30; 0 = all, Pexels stops a search at 10,000). |
| `maxItems` | Cap for the whole run, across all searches and links (0 = no cap). |
| `orientation` | `all`, `landscape`, `portrait` or `square`, the same filter as the Pexels search page. |
| `size` | Minimum width of the original file: `large` (3840 px, 4K), `medium` (1920 px, Full HD) or `all`. |
| `color` | A color name (red, orange, yellow, green, turquoise, blue, violet, pink, brown, black, gray, white) or a hex code like `#2196F3`. |
| `minDuration`, `maxDuration` | Video length in seconds (Pexels caps the filter at 120). |
| `includeDetails` | Adds views, downloads, likes and, for photos, the camera data. Opens one extra page per item. |
| `proxyConfiguration` | Apify Proxy by default; the Actor moves to a residential IP on its own if Pexels refuses the first one. |

`query`, `keyword`, `keywords`, `searchQuery`, `urls`, `maxResults` and `limit` are accepted too, so inputs written
for other Pexels tools keep working.

### Output

Every row has `type` (`photo`, `video` or `error`), so photos and videos can share one dataset.

| Field | What it is |
|---|---|
| `id`, `url` | Pexels id and the page link of the photo or video |
| `title`, `alt`, `description` | Title, alt text and description Pexels shows for the item |
| `width`, `height`, `aspectRatio` | Size of the original file in pixels |
| `avgColor`, `colors` | Average color and the main colors as hex codes |
| `tags` | Every tag Pexels attached to the item |
| `photographer`, `photographerId`, `photographerUsername`, `photographerUrl` | Public name, id, username and profile link of the creator |
| `photographerLocation`, `photographerInstagram`, `photographerTwitter`, `photographerAvatar` | Public profile details, when the creator filled them |
| `license` | License shown by Pexels (`Pexels`) |
| `createdAt`, `publishedAt`, `updatedAt` | When it was uploaded, published and last changed (UTC) |
| `src` | Photo links in 8 sizes: `original`, `large2x`, `large`, `medium`, `small`, `portrait`, `landscape`, `tiny` |
| `downloadUrl` | Direct download link of the full-size file |
| `duration`, `fps` | Video length in seconds and frame rate |
| `videoUrl`, `previewUrl`, `thumbnail`, `thumbnails` | Main MP4, small preview clip and thumbnail images |
| `videoFiles` | Every MP4 rendition with `quality` (sd, hd, uhd), `width`, `height`, `fps` and `link` |
| `views`, `downloads`, `likes` | Counts from the item page (with `includeDetails`, always on single links) |
| `camera`, `cameraMaker`, `aperture`, `focalLength`, `iso`, `shutterSpeed`, `takenAt`, `fileSizeBytes` | Camera data of photos, when the creator kept it |
| `position`, `sourceUrl`, `scrapedAt` | Order in the search or link, what you sent, and when the row was made |

One real photo row (tags and sizes shortened):

```json
{
  "type": "photo",
  "id": 6775303,
  "url": "https://www.pexels.com/photo/large-waves-in-a-sea-6775303/",
  "title": "Large Waves in a Sea",
  "alt": "Captivating image of powerful ocean waves crashing under a clear blue sky, showcasing nature's force.",
  "width": 3000,
  "height": 2001,
  "avgColor": "#A2ADB1",
  "colors": ["#2F4F4F", "#C0C0C0"],
  "tags": ["Aqua", "Blue Sky", "Coast", "Ocean", "Waves"],
  "photographer": "Ben Mack",
  "photographerUrl": "https://www.pexels.com/@ben-mack/",
  "src": {
    "original": "https://images.pexels.com/photos/6775303/pexels-photo-6775303.jpeg",
    "large": "https://images.pexels.com/photos/6775303/pexels-photo-6775303.jpeg?auto=compress&cs=tinysrgb&h=650&w=940"
  },
  "views": 2693156,
  "downloads": 1568,
  "likes": 36,
  "camera": "ILCE-7RM3",
  "cameraMaker": "SONY",
  "aperture": "6.3",
  "iso": 160,
  "createdAt": "2021-02-10T05:49:11.000Z"
}
```

A video row has the same creator and tag fields plus `duration` (for example 16), `fps` (23.98) and a `videoFiles`
list from 360p up to 4K, each with its direct MP4 link.

### How it works

The Actor reads the same public data the Pexels website loads in your browser, page by page, and turns it into flat
rows. Searches return 24 items per page, profiles and collections 12. There is no headless browser, so runs are fast
and light: 30 photos usually take a few seconds.

### Errors you may see

Every error is a row with `errorCode` and is never charged:

| errorCode | Meaning |
|---|---|
| `INVALID_URL` | Not a Pexels search, profile, collection, photo or video link |
| `INVALID_INPUT` | A field has a wrong value (for example an unknown color or orientation) |
| `NOT_FOUND` | The page, profile, photo or video does not exist or was removed |
| `NO_RESULTS` | Pexels returned nothing for this search and these filters |
| `BLOCKED` | Pexels refused every attempt for this source; run it again in a few minutes |
| `NOT_REACHED` | The run timeout or the cost guard arrived before this source |

### Integrations, scheduling and AI agents

- **Schedule** the same searches weekly in [Apify schedules](https://docs.apify.com/platform/schedules) to pick up
  new uploads, or to follow how views and downloads of your favorite photos grow.
- **Export** as JSON, CSV, Excel or XML, or read the dataset from the [Apify API](https://docs.apify.com/api/v2).
- **Connect** it to Make, n8n, Zapier, Google Sheets or Airtable through
  [Apify integrations](https://docs.apify.com/platform/integrations), for example to send new vertical videos to a
  content calendar.
- **AI agents:** call it as a tool through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp)
  in Claude, ChatGPT, Cursor or any MCP client, for example "find 20 landscape photos of mountain lakes with a blue
  tone and give me the large image links with photographer credits".

### FAQ

**Do I need a Pexels API key or account?** No. Everything comes from public Pexels pages, without login, cookies or
a key, and there is no request quota to manage.

**Can I use the photos and videos?** Pexels media is published under the Pexels license, which allows free use, with
some limits (for example, no selling unaltered copies). Read the license on pexels.com before using the files, and
credit the photographer when you can: `photographer` and `photographerUrl` are in every row.

**Does it download the files?** No. It returns direct links (`src`, `downloadUrl`, `videoFiles`) that you can download
with any tool or pass to an image downloader.

**Why are views and downloads empty?** They come from the page of each item, so they are added only with
`includeDetails` on (single photo and video links always include them).

**Is it legal?** The Actor reads public pages only and returns no emails or phone numbers. You are responsible for
how you use the data under the laws that apply to you.

**Something broke or a field is missing?** Open an issue on the Actor page; issues are answered within a day.

### Limitations

- A Pexels collection link returns its first 12 items; the rest of a collection only loads for logged-in visitors.
- Pexels stops any search at 10,000 results; split big topics into several keywords.
- `includeDetails` opens one more page per item, so runs with it take longer.
- Counts are the ones Pexels shows at the moment of the run.

### Changelog

- **16 Oct 2026:** first version: photo and video search with orientation, size, color and duration filters,
  profiles, collections and single links, 8 photo sizes, all video files, views, downloads, likes and camera data.

# Actor input Schema

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

Keywords to search on Pexels, one per line, for example ocean or mountain sunset. Each term is one search.

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

What the search terms return. Links in startUrls keep their own type (a /search/videos/ link always returns videos).

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

Optional. Pexels links, one per line: a search (https://www.pexels.com/search/ocean/ or /search/videos/ocean/, filters in the link are kept), a photographer profile (https://www.pexels.com/@username/), a collection, or a single photo or video page.

## `maxResultsPerSearch` (type: `integer`):

How many photos or videos to collect from each search term or link, in Pexels order. 0 = all of them (Pexels stops a search at 10,000 results).

## `maxItems` (type: `integer`):

Hard cap for the whole run, across all searches and links. 0 = no cap.

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

Same filter as on the Pexels search page. Applies to the search terms.

## `size` (type: `string`):

Minimum width of the original file, using the width filter of the Pexels search page.

## `color` (type: `string`):

Optional. A color name (red, orange, yellow, green, turquoise, blue, violet, pink, brown, black, gray, white) or a hex code like #2196F3. Same color filter as the Pexels search page.

## `minDuration` (type: `integer`):

Videos only. Leave empty for any length.

## `maxDuration` (type: `integer`):

Videos only. Pexels caps this filter at 120 seconds; leave empty for any length.

## `includeDetails` (type: `boolean`):

On: each row also gets the views, downloads and likes shown on its Pexels page and, for photos, the camera data (model, maker, aperture, focal length, ISO, shutter speed, date taken, file size). Opens one extra page per item, so the run takes longer. Same price per item. Single photo and video links always include them.

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

Apify Proxy by default. If Pexels refuses the IP, the Actor moves to a residential IP on its own, at no extra price for you.

## Actor input object example

```json
{
  "searchQueries": [
    "ocean"
  ],
  "mediaType": "photos",
  "maxResultsPerSearch": 30,
  "maxItems": 0,
  "orientation": "all",
  "size": "all",
  "includeDetails": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

No description

## `resultsCsv` (type: `string`):

No description

# 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": [
        "ocean"
    ],
    "maxResultsPerSearch": 30,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapewise/pexels-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": ["ocean"],
    "maxResultsPerSearch": 30,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapewise/pexels-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": [
    "ocean"
  ],
  "maxResultsPerSearch": 30,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call scrapewise/pexels-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapewise/pexels-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/r3ErHhXw4wlr4a21g/builds/AKr6ByC9dxX8tReW3/openapi.json
