# YouTube Shopping Scraper - Merch Shelf, Store & Tagged Products (`s-r/youtube-shopping-scraper`) Actor

Extract the products creators promote on YouTube: channel stores, merch shelves under videos, timestamped product tags and Shorts. Get real titles, prices, merchants, product links, ASINs and affiliate networks with the creator and video for every card.

- **URL**: https://apify.com/s-r/youtube-shopping-scraper.md
- **Developed by:** [SR](https://apify.com/s-r) (community)
- **Categories:** E-commerce, Videos, Social media
- **Stats:** 2 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 product occurrences

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

## YouTube Shopping Scraper

YouTube Shopping Scraper extracts real product cards promoted by creators across channel stores, video merchandise shelves, tagged products and Shorts. Each result connects a product to the creator and video where it appeared, with its displayed merchant, product link, image and available price.

Use this YouTube product scraper to map creator partnerships, monitor merchandise ranges, identify affiliate products and build datasets of products mentioned in videos. Product titles come from the actual cards. Links found only in a description receive a separate confidence label and an empty title, so downstream analysis can distinguish verified cards from unverified links.

### What YouTube Shopping Scraper collects

Channel Store tabs include creator merchandise and products from collaborating merchants. Store results retain the section title, such as “Just dropped” or “Featured”. If the same product appears in two sections, each placement remains a separate occurrence. Channels without a Store tab can still yield products from their videos.

Video merchandise shelves and tagged-product panels are combined into one row for each product in a video. The `surfaces` array records where that product appeared. When YouTube supplies timed tags, `tag_segments` contains every available start and end in seconds. A product displayed on both the shelf and in the player is delivered once for that video.

Shorts use their product cards and shopping panels. Their rows contain `is_short: true`, a Shorts URL and `source_surface: short_product`. Plain video IDs are treated as regular videos; supply a Shorts URL to request a Short explicitly.

Description links are optional and disabled by default. When enabled, external links are delivered as `link_only` occurrences unless they match an existing product card. Known social, newsletter and link-directory hosts are excluded, including their subdomains. Remaining links can point to sponsors, services or other websites. They do not prove that the destination is a specific retail product. The scraper never derives a product title or price from the wording of a link.

### Input

Put mixed inputs in `queries`: channel handles such as `@mkbhd`, channel URLs, channel IDs, video URLs, eleven-character video IDs, Shorts URLs or search phrases. Each entry has its own product limit. Search phrases open videos carrying a shopping badge; channel scans inspect recent uploads because channels do not identify shopping products in their video lists.

Eleven-letter words in lowercase or with a single initial capital, such as `electronics` and `Electronics`, are searched as phrases. Supply a video URL if its ID has that word-like form.

The default `max_products_per_input` is 100. Set `max_videos_per_channel` to control how many recent videos are inspected per channel tab. The default is 30 for Videos and up to 30 for Shorts when Shorts are enabled. Set it to zero for a Store-only run. `max_videos_per_search` defaults to 20 shopping-marked videos for each search phrase.

Use `include_store_tab`, `include_product_shelf`, `include_tagged_products` and `include_shorts` to choose the card surfaces. Each defaults to true. Set `include_description_links` to true if low-confidence external description links are useful to your workflow. Set `geo` to the two-letter country code for the product market; the default is `US`. The `language` value is preserved in results, while source interface text is collected in English for consistent parsing.

The following input is also used in the recorded Store example:

```json
{
  "queries": ["@mkbhd"],
  "max_videos_per_channel": 0
}
```

Collection automatically continues across inputs and large channel scans. The internal `cursor` field is normally managed by the actor. If a run reaches its available collection time, the summary records the remaining continuation and reports incomplete collection.

### Output

The dataset contains one product occurrence per Store section or video binding. A product promoted in two different videos produces two rows. Repeating the same input also preserves its separate input position. The stable `occurrence_id` prevents continuation pages from delivering the same binding twice.

Core fields are `title`, `url`, `image_url`, `country`, `price`, `currency`, `product_id`, `source` and `fetched_at`. `product_id` is the Google offer identifier when YouTube provides it; Store cards and standalone merchandise cards may have no such identifier. `occurrence_id` has a different purpose: it identifies a placement rather than a global product.

Offer details include `merchant_name`, `product_description`, `price_text`, `original_price`, `discount_text`, `reference_price_text`, `availability_text` and `cta_text`. Original display text remains available beside numeric prices. Fields absent from the source are null, including prices on many Amazon cards and in markets where YouTube does not display a price. A missing price never becomes zero.

Attribution fields include `product_url`, `final_product_url`, `product_domain`, `affiliate_network`, `affiliate_tag`, `utm_term_channel` and `commission_disclosed`. Where an affiliate wrapper explicitly contains a destination URL, that destination is decoded locally. Short links are retained without a final destination. Creator links are not clicked to discover their destinations.

Video and creator context includes `video_id`, `video_url`, `video_title`, `view_count`, `published_date`, `channel_id`, `channel_handle`, `channel_title`, `channel_url`, `channel_avatar` and `subscriber_count`. Subscriber counts retain the precision of YouTube’s displayed abbreviations. Relative publication dates remain empty rather than being estimated.

`source_surface`, `surfaces`, `discovery_confidence`, `is_short` and `tag_segments` describe the evidence for each placement. `asin` and `merchant_item_id` are extracted only when explicitly present. This version does not provide retailer-derived GTINs, GS1 verification, brand inference, ratings, reviews or a comparison of prices across other sellers. `enrichment_level` is zero or one and describes whether a destination is available from the supplied link itself.

#### Output example

This is the first row of a real run on the video `WaHwmSv1erM` (input `{"queries": ["WaHwmSv1erM"]}`), collected on 2 October 2026. The same product appeared on the merch shelf and as a tagged product between second 31 and 55, so it is delivered once with both surfaces. The run returned 35 product rows.

```json
{
  "source": "youtube-shopping-scraper",
  "fetched_at": "2026-10-02T13:27:05.176Z",
  "title": "Blink Outdoor 2K+ (newest model) - Wireless smart security camera, 2K video resolution, enhanced audio, long-lasting battery. Sync Module Core",
  "url": "https://www.lowes.com/pd/Blink-Outdoor2K-5CAM-Black/5016801981?user=shopping&feed=yes",
  "image_url": "https://encrypted-tbn3.gstatic.com/shopping?q=tbn:ANd9GcQsDUkDFSn2e9tAzDVXWgxndAJpTpcvt5D45QPvt45orGglFjY",
  "country": "US",
  "price": 119.99,
  "currency": "USD",
  "product_id": "16663594364602218020",
  "occurrence_id": "7293edca6c01a4a1",
  "product_url": "https://lowes.sjv.io/c/3586222/897039/12374?u=https%3A%2F%2Fwww.lowes.com%2Fpd%2FBlink-Outdoor2K-5CAM-Black%2F5016801981%3Fuser%3Dshopping%26feed%3Dyes&subid1=YT3-3sPyMxt6E_ZYVyOghY5mA4iIyDksZYMLVjfyR1b-TwW-iP9RsKETA8Jzu8iFNuCLUl28WuR-0bBNR3dbPhQfYk2UQY1bWw",
  "final_product_url": "https://www.lowes.com/pd/Blink-Outdoor2K-5CAM-Black/5016801981?user=shopping&feed=yes",
  "product_domain": "lowes.com",
  "product_description": "See and hear more — better than ever. Battery-powered Outdoor 2K+ delivers sharp 2K video resolution, detailed 4x digital zoom, and crystal-clear two-way audio with advanced noise cancellation. Mount in minutes with no wires, no worries, no compromises. Blink Outdoor 2K+ (newest model) - Wireless smart security camera, 2K video resolution, enhanced audio, long-lasting battery. Sync Module Core",
  "price_text": "$119.99",
  "original_price": null,
  "discount_text": null,
  "reference_price_text": null,
  "availability_text": "Limited stock",
  "merchant_name": "Lowe's",
  "merchant_logo": "https://encrypted-tbn2.gstatic.com/shopping?q=tbn:ANd9GcQdpH7-eg9Sxa9xwp52szmeirTRxhi6DDpeftkBLQS44aV4rkI",
  "merchant_item_id": "5016801981",
  "asin": null,
  "affiliate_network": "impact",
  "affiliate_tag": "YT3-3sPyMxt6E_ZYVyOghY5mA4iIyDksZYMLVjfyR1b-TwW-iP9RsKETA8Jzu8iFNuCLUl28WuR-0bBNR3dbPhQfYk2UQY1bWw",
  "utm_term_channel": null,
  "commission_disclosed": true,
  "cta_text": "View on YouTube",
  "section_title": null,
  "surfaces": [
    "product_shelf",
    "tagged_product"
  ],
  "source_surface": "tagged_product",
  "discovery_confidence": "tag_card",
  "tag_segments": [
    {
      "start_seconds": 31,
      "end_seconds": 55
    }
  ],
  "video_id": "WaHwmSv1erM",
  "video_url": "https://www.youtube.com/watch?v=WaHwmSv1erM",
  "video_title": "Best Amazon Prime Big Deal Days 2026 Early Deals [35 Deals You Can't Miss!]",
  "view_count": 7743,
  "published_date": "2026-10-01",
  "is_short": false,
  "channel_id": "UCPivGkDwFySKlZR_8nO8lGA",
  "channel_handle": "@validconsumer",
  "channel_title": "Valid Consumer",
  "channel_url": "https://www.youtube.com/channel/UCPivGkDwFySKlZR_8nO8lGA",
  "subscriber_count": 129000,
  "channel_avatar": "https://yt3.ggpht.com/36CaF-NoSSP33SDfG_GOIjSZXwqO87m6B72UM2L4zJo5xFJOhCgHquA1xDLt_jdgtVXmJ-Y6=s176-c-k-c0x00ffffff-no-rj",
  "language": "en",
  "input": "WaHwmSv1erM",
  "enrichment_level": 1
}
```

### Pricing

The intended publication model is pay per event: **$4 per 1,000 delivered product occurrences**, plus a **$0.0001 actor start event**. The live Pricing tab is authoritative once the actor is published. There are no identity-enrichment or market-comparison events in this version.

Each delivered dataset row corresponds to one `product` event. Combined shelf and tag appearances in the same video are billed as one occurrence. Enabled description-link rows count as occurrences too. Empty results and source warnings produce no product events; the platform start event still applies. Non-paying users receive at most ten rows per run. Paying users can request the configured limits across all their inputs.

### Use cases

- **Creator merch inventory**: list every item in a creator's YouTube Store, grouped by section, to track drops and price changes.
- **Brand and agency research**: see which merchants, products and affiliate networks a creator promotes, and at which second of the video a product is tagged.
- **Affiliate and partnership analysis**: find which creators push products from a retailer or network, using `merchant_name`, `product_domain` and `affiliate_network`.
- **Ecommerce and price monitoring**: watch the prices and stock texts YouTube shows on shopping cards for products you sell.
- **Shorts commerce**: collect the products attached to Shorts, which most YouTube scrapers skip.

For a creator merchandise inventory, start with a channel and set the video limit to zero. For campaign research, supply a set of videos and compare merchants, affiliate networks and timed product placements. For discovery, use a focused search phrase, then retain `tag_card` and `shelf_card` rows for analysis. For broader sponsor research, enable description links and review `link_only` rows separately.

Always compare records within the same country. YouTube can select different merchants for different markets, and a price available in the US may be absent elsewhere. These are observations of YouTube’s shopping display at collection time, rather than a promise of the merchant’s current checkout price or stock. Review the summary warnings when a run reports partial collection.

### Comparison with other YouTube product scrapers

| | This actor | Channel store scrapers | Description-link discovery tools |
|---|---|---|---|
| Channel Store tab | yes, with section titles | yes | no |
| Merch shelf under videos | yes | no | yes |
| Tagged products with timestamps | yes, start and end seconds | no | no |
| Shorts product cards | yes | no | partly |
| Product titles | from the real card | from the real card | often guessed from link text |
| Numeric price and currency | yes, plus original display text | price text only | no |
| Merchant, ASIN, offer id | when YouTube shows them | merchant only | retailer domain |
| Affiliate network and decoded destination | yes | no | yes |
| Input | handles, channel URLs and IDs, videos, Shorts, search phrases | channel IDs | queries, channels, videos |

A general YouTube scraper returns videos, comments or channel statistics. This YouTube shopping scraper focuses on the commerce layer: every product card a viewer can click, tied to the creator and the video.

### FAQ

#### Does this YouTube merch shelf scraper include creator stores?

Yes. Store cards, video shelves, product tags and Shorts cards can be collected in the same run. Store sections remain identifiable on each row.

#### Why are some prices empty?

YouTube does not supply prices for every merchant or market. Amazon shopping cards frequently have no displayed price. Empty source prices remain null in the dataset.

#### Can I use this as a YouTube affiliate scraper?

Yes. The original attribution link, detected affiliate network and available tracking tag are retained. Destination URLs embedded in known wrappers are decoded without visiting those links.

#### Which description links are excluded?

Known social, newsletter and link-directory hosts are skipped: Patreon, Linktree, Kit/ConvertKit, Substack, Spotify, Twitch, Threads and Reddit, alongside YouTube, Google, Instagram, Facebook, X/Twitter, TikTok and Discord. This also applies to their subdomains. Product short links and merchant links remain available as `link_only` rows, with no guessed title or price.

#### Do all YouTube tagged products have timestamps?

Only products with explicit time windows receive populated `tag_segments`. A product-list card without a timed tag remains useful evidence but has an empty segment array.

#### Do I need a YouTube account or API key?

No. The actor reads the public shopping cards that any viewer sees. You only supply channels, videos, Shorts or search phrases.

#### What happens if a channel handle does not exist?

That input returns no rows and is not billed. The run summary records a "not found" warning for it, and the other inputs in the same run are still collected.

#### Is this a separate actor from a regular YouTube scraper?

Yes. Video, comment and channel data are covered by general YouTube scrapers. This actor returns only products, so you pay per product row and not for videos without shopping cards.

#### Does this actor verify EANs or compare other merchants?

No. This version collects shopping-card data and locally available link information. It does not claim a barcode, retailer identity or market price that YouTube has not supplied.

# Actor input Schema

## `queries` (type: `array`):

YouTube channel handles or URLs, channel IDs, video URLs or IDs, Shorts URLs, or search phrases. Each entry is processed separately. Bare 11-letter words in lowercase or with a single initial capital are searched; use a video URL for an ambiguous ID.

## `max_products_per_input` (type: `integer`):

Maximum product occurrences per input, across all requested surfaces.

## `max_videos_per_channel` (type: `integer`):

Maximum recent videos per channel tab (Videos and, when enabled, Shorts). Set 0 to collect only Store cards.

## `max_videos_per_search` (type: `integer`):

Maximum videos with a shopping badge to open for each search phrase.

## `include_store_tab` (type: `boolean`):

Collect channel Store cards, including merchant collaborations.

## `include_product_shelf` (type: `boolean`):

Collect merchandise cards displayed below videos.

## `include_tagged_products` (type: `boolean`):

Collect product tags and list panels, including all available start/end time windows.

## `include_shorts` (type: `boolean`):

Collect Shorts products and visit the Shorts tab of channels.

## `include_description_links` (type: `boolean`):

Include external description links as low-confidence link_only rows. Such links may be sponsors or websites rather than product pages; no title or price is inferred.

## `geo` (type: `string`):

Two-letter country code controlling the product market. US has the best displayed price coverage.

## `language` (type: `string`):

Language code echoed in the output. YouTube is requested in English for consistent source text and date/price parsing.

## Actor input object example

```json
{
  "queries": [
    "https://www.youtube.com/@mkbhd",
    "https://www.youtube.com/watch?v=WaHwmSv1erM"
  ],
  "max_products_per_input": 100,
  "max_videos_per_channel": 30,
  "max_videos_per_search": 20,
  "include_store_tab": true,
  "include_product_shelf": true,
  "include_tagged_products": true,
  "include_shorts": true,
  "include_description_links": false,
  "geo": "US",
  "language": "en"
}
```

# Actor output Schema

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

Collected product occurrences.

## `output` (type: `string`):

Delivered rows, charges, free-tier status and warnings.

# 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 = {
    "queries": [
        "https://www.youtube.com/@mkbhd",
        "https://www.youtube.com/watch?v=WaHwmSv1erM"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("s-r/youtube-shopping-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 = { "queries": [
        "https://www.youtube.com/@mkbhd",
        "https://www.youtube.com/watch?v=WaHwmSv1erM",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("s-r/youtube-shopping-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 '{
  "queries": [
    "https://www.youtube.com/@mkbhd",
    "https://www.youtube.com/watch?v=WaHwmSv1erM"
  ]
}' |
apify call s-r/youtube-shopping-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,s-r/youtube-shopping-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/lrjbo5opMglnCkF6o/builds/qfm8aCjx85zFz7Hr4/openapi.json
