# Instagram Shop Scraper · Products, Prices & Emails · No Login (`memo23/instagram-shop-products-scraper`) Actor

Scrape any Instagram Shop by handle. Get every product with its price, sale price and discount, image and buy link, plus the merchant card behind the shop — business address, contact email, phone and website. No login, no cookies. JSON, CSV, Excel.

- **URL**: https://apify.com/memo23/instagram-shop-products-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** E-commerce, Social media, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.40 / 1,000 products

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

## Instagram Shop Scraper

Scrape any brand's Instagram Shop by handle.

Get every product with its **price, sale price and discount**, the image, and the link that
actually sells it — plus the merchant card behind the shop: **business address, contact email,
phone and website**. No login, no cookies, no account risk.

Feed it `fashionnova` and get 33 products and the shop's contact email in one run.

***

### Why Use This Scraper?

- **The products Instagram shows on the shop tab** — title, current price, full price, image, buy link
- **Discounts already worked out** — `isDiscounted` and `discountPercent` computed from the two prices, so a price-drop filter is one click
- **Merchant contact data** — business address, contact email, phone, website and privacy-policy URL from Instagram's own "About this shop" panel
- **Multi-currency** — prices come back in the shop's own currency with the symbol split into its own field
- **Accounts without a shop cost you nothing** — Instagram's own shop flag is checked first, so a handle with no shop returns one labelled row instead of burning requests
- **Products deduplicated across collections** before they are delivered or charged
- **Many accounts per run**, processed in parallel
- No login, no cookies, no session tokens

***

### Overview

The Instagram Shop Scraper is built for competitive pricing teams, e-commerce analysts, dropshippers
and lead-generation teams who need to see what a brand sells on Instagram and how to reach that brand.

The output is **two row shapes in one dataset**, labelled by `resultsType`:

- `shop` — one row per account: merchant name, category, follower count, business address, contact email, phone, website, checkout style, and how many collections and products were found
- `product` — one row per item: title, price, full price, discount percentage, currency, image, buy link and which collection it came from

Ask for one or both with `resultsType`.

***

### Supported Inputs

#### Input types

| Input | Example | Notes |
|---|---|---|
| Handle | `fashionnova` | The usual case |
| @-handle | `@fashionnova` | The `@` is stripped |
| Profile URL | `https://www.instagram.com/fashionnova/` | Any subdomain, trailing path or query is fine |

#### Copy-pasteable input

```json
{
  "usernames": ["fashionnova", "skims", "aloyoga", "zara"],
  "resultsType": "all",
  "maxProductsPerShop": 50
}
```

#### Unsupported inputs

- Post, reel and explore URLs — this actor takes accounts, not posts
- Private accounts — a private account has no public shop
- Product URLs or product IDs as input — products are discovered from the shop, not looked up individually

***

### Use Cases

| Who | Problem | How |
|---|---|---|
| Competitive pricing | Track what a rival charges and when they discount | Run the rival's handles daily, diff `priceAmount` between runs |
| Price-drop monitoring | Catch sales as they start | Set `onlyDiscounted` and watch `discountPercent` |
| Dropshipping / sourcing | Find what is selling and where it ships from | Products plus `websiteUrl` and `businessAddress` on the shop row |
| B2B lead generation | Reach the brands behind Instagram shops | `resultsType: "shop"` returns contact email, phone and address per account |
| Market research | Size a category's price band | Sweep a list of brand handles and aggregate `priceAmount` by `category` |
| Affiliate / catalogue building | Build a product feed with images and buy links | Every product row carries `imageUrl` and `externalUrl` |

***

### How It Works

1. Each input is normalised to a handle, whether given as a handle, an @-handle or a profile URL.
2. The profile is fetched once. Instagram publishes a flag saying whether the account has a shop — if it says no, the account returns a labelled row and no shop requests are spent on it.
3. The shop front is fetched: merchant identity, its collections, and the products displayed on the front itself.
4. Each collection is paged for the products it holds. Products are deduplicated against everything already seen for that account, because the shop front and the collections overlap.
5. With the shop card requested, Instagram's "About this shop" panel supplies the business address, contact email, phone and website.
6. Rows are charged and delivered: one `shop` event per account, one `product` event per item.

***

### Input Configuration

| Field | Type | Default | Description |
|---|---|---|---|
| `usernames` | array | — | Accounts to scrape. Handles, @-handles or profile URLs. **Required.** |
| `resultsType` | string | `all` | `all`, `shop` (contact data only), or `products` |
| `maxProductsPerShop` | integer | unlimited | Cap products per account |
| `onlyDiscounted` | boolean | `false` | Return only items priced below their full price |

#### Example — contact data for a list of brands

```json
{
  "usernames": ["skims", "aloyoga", "sephora", "fashionnova"],
  "resultsType": "shop"
}
```

#### Example — today's sale items only

```json
{
  "usernames": ["zara", "fashionnova"],
  "resultsType": "products",
  "onlyDiscounted": true,
  "maxProductsPerShop": 100
}
```

***

### Output Overview

Two row shapes, split on `resultsType`. Every row also carries `input`, the exact string you
supplied, so results map back to your list even when a handle redirects.

Accounts that cannot be delivered return a row with `error`, `errorMessage` and `errorKind`
instead — see the FAQ for what each one means.

***

### Output Samples

**A product row**

```json
{
  "input": "fashionnova",
  "resultsType": "product",
  "username": "fashionnova",
  "userId": "29883180",
  "merchantId": "17841401775400466",
  "merchantUsername": "fashionnova",
  "productId": "27671422119202612",
  "title": "Women's Alina Turtleneck Ribbed Midi Dress in Black",
  "price": "$12.00",
  "priceAmount": 12.0,
  "fullPrice": "$24.99",
  "fullPriceAmount": 24.99,
  "isDiscounted": true,
  "discountPercent": 52,
  "currency": "$",
  "imageUrl": "https://scontent-iad3-1.cdninstagram.com/v/t45.5328-4/797597465_...jpg",
  "imageWidth": 1200,
  "imageHeight": 1200,
  "externalUrl": "https://www.fashionnova.com/products/alina-turtleneck-ribbed-midi-dress-black",
  "checkoutStyle": "multi_item_checkout",
  "collectionId": "seller_curated_v2:6672978339415599:29883180",
  "collectionType": "seller_curated_v2"
}
```

**A shop row**

```json
{
  "input": "skims",
  "resultsType": "shop",
  "username": "skims",
  "userId": "8688762057",
  "fullName": "SKIMS",
  "isVerified": true,
  "category": "Clothing (Brand)",
  "followerCount": 8100000,
  "profileUrl": "https://www.instagram.com/skims/",
  "hasShop": true,
  "merchantId": "17841401775400466",
  "merchantUsername": "skims",
  "shopName": "SKIMS",
  "businessAddress": "PO Box 1339, Culver City, CA 90232 - US",
  "email": "help@skims.com",
  "phone": "+17477775467",
  "websiteUrl": "https://checkout.skims.com",
  "privacyPolicyUrl": "https://checkout.shopify.com/25954484284/policies/12343771196.html?locale=en",
  "logoUrl": "https://scontent-lhr11-1.cdninstagram.com/v/t39.30808-1/355872632_...jpg",
  "checkoutStyle": "multi_item_checkout",
  "collectionCount": 2,
  "productCount": 8
}
```

***

### Key Output Fields

**`product` rows**

`productId`, `title`, `price`, `priceAmount`, `fullPrice`, `fullPriceAmount`, `isDiscounted`, `discountPercent`, `currency`, `imageUrl`, `imageWidth`, `imageHeight`, `externalUrl`, `checkoutStyle`, `collectionId`, `collectionType`, `merchantId`, `merchantUsername`

**`shop` rows**

`username`, `userId`, `fullName`, `isVerified`, `category`, `followerCount`, `biography`, `profileUrl`, `merchantId`, `merchantUsername`, `shopName`, `businessAddress`, `email`, `phone`, `websiteUrl`, `privacyPolicyUrl`, `logoUrl`, `checkoutStyle`, `collectionCount`, `productCount`

`price` keeps Instagram's own formatting (`"$12.00"`, `"€3.59"`); `priceAmount` is the same value
as a number for sorting and arithmetic, and `currency` holds just the symbol.

***

### FAQ

**Which accounts have an Instagram shop?**
Brands that sell through Instagram's own shop tab. In a sample of twelve large accounts, nine had
one. Creator and media accounts usually do not, and Nike removed theirs. The actor checks
Instagram's own flag before spending anything, so a handle without a shop costs one request and
returns a row saying `no_shop`.

**Do I get the brand's whole catalogue?**
No, and no tool can — Instagram's shop feed is a curated window the merchant controls, typically
10 to 40 products, not the full catalogue behind their website. Every product carries
`externalUrl` pointing at the merchant's own product page.

**What does `shop_unavailable` mean?**
The profile says the account has a shop but Instagram would not render it. It is an Instagram-side
failure and it often clears — retry that handle later. Two of ten live shops behaved this way
during testing, so expect it occasionally rather than never.

**Are prices in my currency?**
They are in the shop's currency, as Instagram serves it to a logged-out visitor. `currency` holds
the symbol so you can group or convert afterwards. Zara returns euros, Fashion Nova dollars.

**How is `discountPercent` calculated?**
From `fullPriceAmount` and `priceAmount`, rounded to the nearest percent, and only when the full
price is genuinely higher. Some shops send the two prices equal on non-sale items, which is why
presence of `fullPrice` alone is not treated as a discount.

**Does `maxProductsPerShop` interact with `onlyDiscounted`?**
The cap applies after the filter, so asking for 5 with `onlyDiscounted` gives you 5 sale items,
not the sale items among the first 5 products.

**Am I charged for accounts with no shop?**
No. Rows carrying `error` are never charged.

***

### Support

Found a bug or need a field that is not there? Open an issue on the actor's **Issues** tab and it will be looked at.

Email: muhamed.didovic@gmail.com

***

### Additional Services

Need a custom scraper, a tailored export format, or an integration into your own pipeline? Custom builds are available — get in touch at muhamed.didovic@gmail.com.

***

### Explore More Scrapers

- **Instagram Profile Scraper** — profiles, posts and comments from any public account
- **Instagram Hashtag Scraper** — top posts and reels from any public hashtag
- **Instagram Location Scraper** — place cards with coordinates, contact data and tagged posts
- **Instagram Similar Profiles & Lookalike Finder** — map a niche from one seed account
- **Instagram Stories & Highlights Scraper** — active stories and permanent highlights
- **Instagram Comments Scraper** — full comment threads with replies
- **Instagram Tagged Posts Scraper** — every post where an account is tagged

Browse the full collection at [apify.com/memo23](https://apify.com/memo23).

***

### 🤖 For AI Agents & LLM Apps

Compact reference for AI agents calling this actor via the [Apify MCP server](https://mcp.apify.com) or the Apify API (actor: `memo23/instagram-shop-products-scraper`).

**Purpose:** Returns the product catalogue shown on a brand's Instagram shop tab, plus the merchant's published contact details.

**Minimal input:**

```json
{ "usernames": ["fashionnova"], "resultsType": "all", "maxProductsPerShop": 50 }
```

**Output:** two row shapes in one dataset, distinguished by `resultsType`. `product` rows carry productId, title, price, priceAmount, fullPrice, fullPriceAmount, isDiscounted, discountPercent, currency, imageUrl, imageWidth, imageHeight, externalUrl, checkoutStyle, collectionId, collectionType. `shop` rows carry username, userId, fullName, isVerified, category, followerCount, biography, profileUrl, merchantId, merchantUsername, shopName, businessAddress, email, phone, websiteUrl, privacyPolicyUrl, logoUrl, checkoutStyle, collectionCount, productCount. Accounts that cannot be delivered return `{input, resultsType: "error", error, errorMessage, errorKind}`.

**Behaviors an agent should know:**

- `resultsType: "shop"` skips product collection entirely — use it when only contact data is needed.
- An account with no Instagram shop returns `error: "no_shop"` with `errorKind: "unavailable"`; it is an answer, not a failure, and is not charged.
- `error: "shop_unavailable"` (`errorKind: "failed"`) means the shop exists but Instagram did not render it. Retrying that handle later usually works.
- Instagram's shop feed is a curated subset, so expect roughly 10–40 products per shop regardless of how high `maxProductsPerShop` is set.
- `onlyDiscounted` filters before `maxProductsPerShop` caps.
- Products are deduplicated per account across the shop front and its collections before delivery and billing.
- Billing: one `shop` event per shop row, one `product` event per product row. Error rows are never charged.
- No login is used, so no authenticated-only fields are available.

***

### ⚠️ Disclaimer

This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by Meta Platforms, Inc. or any of its subsidiaries. All trademarks mentioned are the property of their respective owners.

The scraper accesses only publicly available Instagram shop pages — no authenticated endpoints, paid features, or content behind the instagram.com login wall. Product prices, images and merchant details belong to the merchants that published them. Users are responsible for ensuring their use complies with instagram.com's Terms of Service, applicable data-protection law (GDPR, CCPA, etc.), and any contractual obligations of their own organization.

***

### SEO Keywords

instagram shop scraper, instagram shopping scraper, scrape instagram products, instagram product scraper, instagram store scraper, instagram catalogue scraper, instagram price scraper, instagram ecommerce data, instagram merchant email scraper, brand contact scraper instagram, instagram shop API, competitor price monitoring instagram, instagram dropshipping research, product feed instagram, instagram shop products export, discount tracking instagram, instagram.com scraper, Apify instagram, no login instagram scraper

# Actor input Schema

## `usernames` (type: `array`):

The shops to scrape — one per line. A handle (sephora), an @handle (@sephora), or a profile URL (https://www.instagram.com/sephora/) all work. Only accounts with an Instagram shop return products; anything else comes back as a labelled row saying so, and costs you nothing.

## `resultsType` (type: `string`):

The shop card is one row per account: merchant name, business address, contact email, phone, website and category. Products are one row each, with price, sale price, discount, image and buy link. Default returns both.

## `maxProductsPerShop` (type: `integer`):

Cap how many products to collect per account. Leave empty for everything the shop front and its collections serve — typically 10 to 40 products, since Instagram's shop feed is a curated window rather than the merchant's full catalogue.

## `onlyDiscounted` (type: `boolean`):

Return only products whose price is below their full price, and skip the rest before they are charged. Useful for price-drop monitoring. Default: off.

## Actor input object example

```json
{
  "usernames": [
    "fashionnova",
    "skims",
    "aloyoga"
  ],
  "resultsType": "all",
  "onlyDiscounted": false
}
```

# Actor output Schema

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

Filter on resultsType to split the two row shapes: 'shop' for merchant contact data, 'product' for the catalogue.

# 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 = {
    "usernames": [
        "fashionnova"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/instagram-shop-products-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 = { "usernames": ["fashionnova"] }

# Run the Actor and wait for it to finish
run = client.actor("memo23/instagram-shop-products-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 '{
  "usernames": [
    "fashionnova"
  ]
}' |
apify call memo23/instagram-shop-products-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,memo23/instagram-shop-products-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/mwNLarTB2HlZaR3ln/builds/xWmbwodIU9AnYPuKd/openapi.json
