# Walgreens Products & Reviews Scraper (`abotapi/walgreens-com`) Actor

Scrape Walgreens products by keyword, category or product URL. Extract prices, promotions, availability, ingredients, descriptions, product details, ratings and customer reviews in clean, structured data.

- **URL**: https://apify.com/abotapi/walgreens-com.md
- **Developed by:** [Abot API](https://apify.com/abotapi) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 product records

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

## Walgreens Products & Reviews Scraper

Collect Walgreens products by keyword, category links, or individual product links, with optional full product information and individual customer reviews. Each result includes identifiers, current catalog price, stock indicators, size, ingredients where supplied, offers, and rating totals. Products from the selected mode are combined and deduplicated in one dataset.

### Why This Scraper?

- Collect product data across one or more Walgreens categories.
- Set a product limit for keyword and category collections.
- Capture product and SKU identifiers, UPC and GTIN codes.
- Include online and store stock labels, prices, coupons, and offers.
- Include the average rating and review count shown in the catalog.
- Add descriptions, warnings, uses, shipping information, and customer review text.
- Track product changes in recurring runs, with optional expired rows.

### Use Cases

- **Price and promotion tracking:** capture current, regular and sale prices, coupons and offers across one or more categories or search terms to see how pricing moves over time.
- **Stock and availability monitoring:** check online and in-store stock labels for specific products or a whole category before restocking or promoting them elsewhere.
- **Product content and catalog building:** collect titles, brands, sizes, descriptions, ingredients, warnings and full image galleries to populate a catalog, comparison site or app.
- **Customer sentiment research:** collect individual review text, ratings and review counts to see what shoppers say about specific products or brands.
- **Recurring catalog audits:** schedule the actor with Incremental mode to see only new, updated, reappeared or expired products between scans, instead of re-downloading everything each time.
- **Downstream automation:** send a condensed product summary into Notion, Linear, Airtable or another connected app through the optional MCP export, while the complete record stays in the dataset.

### Data You Get

| Field | Example |
|---|---|
| `id` | `00000001` |
| `title` | `Sample Product` |
| `brand` | `Sample Brand` |
| `url` | `https://www.walgreens.com/store/c/sample-product/ID=00000001-product` |
| `price` | `$5.00` |
| `imageUrl` | Primary product photo URL |
| `images` | Distinct full-size gallery photo URLs |
| `productDetails` | Full product information object |
| `catalogProduct` | All available catalog attributes |
| `descriptionText` | `Sample product description` |
| `reviews` | Review text, rating, date, media, and public author attributes |
| `productSize` | `5 oz` |
| `productType` | `Personal care` |
| `gtin` | `0000000000000` |
| `upc` | `000000000000` |
| `rating` | `4.5` |
| `reviewCount` | `100` |
| `onlineInvStatus` | `instock` |
| `reviewTotal` | `100` |
| `couponCode` | `Sample coupon` |
| `offerDescription` | `Sample offer` |
| `changeType` | `UPDATED` |
| `changedFields` | `["price"]` |
| `firstSeenAt` | `2026-01-01T00:00:00Z` |
| `lastSeenAt` | `2026-01-02T00:00:00Z` |

The actor passes through additional catalog attributes when Walgreens supplies them. Enable `fetchDetails` for the complete product information object and parsed description, ingredient, warning, use, and shipping sections. Enable `fetchReviews` for individual reviews. A product may have no reviews or may omit some detail sections. Products marked “Priced Per Store” are retained with a null catalog price and the original pricing message.

### How to Use

Choose **Search mode** for keywords, brands, product types, price/rating filters, availability, offers, and sorting. Choose **URL mode** for category, search-result, or product links; keyword inputs, filters, and sorting are ignored in URL mode. Category links must end in `productlist.jsp` and include the `N` category parameter. Search-result links use `/search/results.jsp?Ntt=...`. Supplied starting pages and URL filters are retained. Product links must contain `/ID=...-product`. Both modes include runnable sample inputs. The default is Search mode with `toothpaste`.

> Sample shape, values are illustrative placeholders.

```json
{
  "mode": "url",
  "urls": ["https://www.walgreens.com/store/store/category/productlist.jsp?N=20003053"],
  "maxItems": 20,
  "fetchDetails": true,
  "fetchReviews": true,
  "maxReviewsPerProduct": 20
}
```

For a keyword collection, enter one or more search terms and set the product cap.

> Sample shape, values are illustrative placeholders.

```json
{
  "mode": "search",
  "searchQueries": ["vitamins", "toothpaste"],
  "maxItems": 500,
  "sortBy": "price_asc"
}
```

Several category links can be scanned together. Products appearing in several categories are saved once per run.

> Sample shape, values are illustrative placeholders.

```json
{
  "mode": "url",
  "urls": [
    "https://www.walgreens.com/store/store/category/productlist.jsp?N=20003053",
    "https://www.walgreens.com/store/store/category/productlist.jsp?N=360341"
  ],
  "maxItems": 100
}
```

To compare a recurring catalog scan against the prior run, turn on incremental mode. A separate baseline is always kept for each mode, source set, filter selection, and enrichment configuration. `stateKey` is optional and only adds a name on top of that, for example to keep two schedules with identical inputs apart.

> Sample shape, values are illustrative placeholders.

```json
{
  "mode": "url",
  "urls": ["https://www.walgreens.com/store/store/category/productlist.jsp?N=20003053"],
  "incrementalMode": true,
  "emitUnchanged": false,
  "emitExpired": false,
  "maxItems": 0
}
```

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/walgreens-com").call(run_input={"mode": "search", "searchQueries": ["toothpaste"], "maxItems": 20})
for product in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(product["title"], product["price"])
```

JavaScript:

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/walgreens-com').call({ mode: 'search', searchQueries: ['toothpaste'], maxItems: 20 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the **Integrations** tab.

### Input Parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `search` | Choose Search or URL mode. |
| `urls` | string array | Sample category | Links used only in URL mode. |
| `searchQueries` | string array | `["toothpaste"]` | Keywords used only in Search mode. |
| `brands` | string array | Empty | Exact brand names, such as Crest or Colgate. |
| `productTypes` | string array | Empty | Exact product types, such as Toothpaste. |
| `minPrice` | number | Empty | Minimum current price in USD. |
| `maxPrice` | number | Empty | Maximum current price in USD. |
| `minRating` | number | Empty | Minimum rating from 0 to 5. |
| `onlineOnly` | boolean | `false` | Require in-stock online availability. |
| `offersOnly` | boolean | `false` | Require an offer or discounted price. |
| `sortBy` | string | `relevance` | Relevance, price ascending/descending, highest rated, or most reviewed; applied separately per search term. |
| `maxItems` | integer | `20` | Product cap across all selected sources. `0` means no cap. |
| `maxPages` | integer | Empty (unlimited) | Optional source page limit. Blank or `0` leaves Max items as the only default cap. |
| `fetchDetails` | boolean | `false` | Include complete product information, detail sections, and the full image gallery. |
| `fetchReviews` | boolean | `false` | Include individual customer reviews, newest first. |
| `maxReviewsPerProduct` | integer | `20` | Review cap per product. `0` collects all available reviews. |
| `resumeFromRunId` | string | Empty | Earlier run or dataset ID whose product IDs should be skipped. |
| `incrementalMode` | boolean | `false` | Label new, updated, unchanged, and reappeared products. |
| `stateKey` | string | Automatic | Optional name for a recurring baseline. |
| `emitUnchanged` | boolean | `false` | Include unchanged products in recurring runs. |
| `emitExpired` | boolean | `false` | Include expired rows after a complete recurring scan. |
| `proxy` | object | Direct connection | Optional connection settings for collection requests. |
| `mcpConnectors` | array | Empty | Optional authorized app connectors. |
| `notionParentPageUrl` | string | Empty | Parent page for a Notion export. |
| `maxNotifyListings` | integer | `50` | Maximum product summaries exported per connector. |

### Send results into your apps (MCP connectors)

Authorize a connector in Apify Settings under Integrations, then select it in the **Export to your apps (MCP connectors, optional)** input section. For Notion, set `notionParentPageUrl` to the parent page. `maxNotifyListings` limits the export.

Exports contain a condensed product summary with a title and key fields. Nested product information and review collections are shortened in summaries. The complete product and review record stays in the Apify dataset. An export failure leaves the dataset available.

`imageUrl` is the primary catalog image. `images` contains distinct product photos at the largest supplied size; enable `fetchDetails` for the full gallery. Original gallery URLs and image sizes remain in `productDetails`.

The Output tab offers **Products** and **Reviews** views. Products includes the primary photo and gallery URLs. Reviews shows one collected review per row with its product ID and name. Enable `fetchReviews` to populate it. **All fields** retains complete product records and nested review data.

### Output Example

> Sample shape, values are illustrative placeholders.

```json
{
  "id": "00000001",
  "prodId": "00000001",
  "skuId": "00000002",
  "title": "Sample Product",
  "productName": "Sample Product",
  "brand": "Sample Brand",
  "url": "https://www.walgreens.com/store/c/sample-product/ID=00000001-product",
  "imageUrl": "https://pics.walgreens.com/prodimg/000000/450.jpg",
  "images": ["https://pics.walgreens.com/prodimg/000000/900.jpg", "https://pics.walgreens.com/prodimg/000000/2_900.jpg"],
  "price": "$5.00",
  "regularPrice": "$6.00",
  "salePrice": "$5.00",
  "currency": "USD",
  "productSize": "5 oz",
  "productType": "Personal care",
  "gtin": "0000000000000",
  "upc": "000000000000",
  "rating": "4.5",
  "reviewCount": "100",
  "ingredientName": "Sample active ingredient",
  "inactiveIngredients": "Sample inactive ingredient",
  "onlineInvStatus": "instock",
  "storeInventoryStatus": "In Stock",
  "couponCode": "Sample coupon",
  "offerDescription": "Sample offer",
  "productDetails": {"productInfo": {"productId": "00000001", "title": "Sample Product"}, "prodDetails": {"section": []}},
  "catalogProduct": {"prodId": "00000001", "skuId": "00000002", "productDisplayName": "Sample Product", "priceInfo": {"regularPrice": "$6.00", "salePrice": "$5.00"}},
  "descriptionText": "Sample product description",
  "reviews": [{"Id": "sample-review-1", "ProductId": "00000001", "Title": "Sample review", "ReviewText": "Illustrative review text", "Rating": 5, "SubmissionTime": "2026-01-01T00:00:00Z", "UserNickname": "Sample Reviewer"}],
  "reviewsFetched": 1,
  "reviewTotal": 100,
  "changeType": "UPDATED",
  "changedFields": ["price"],
  "firstSeenAt": "2026-01-01T00:00:00Z",
  "lastSeenAt": "2026-01-02T00:00:00Z"
}
```

### Plan Requirement

An Apify account is needed to run the actor. The selected connection settings may affect availability and usage charges.

### FAQ

#### How much does it cost?

You pay per product record returned, plus an optional charge when full product information or customer reviews are actually collected for a product, and a one-time charge when a run starts. Scraping a product link directly already requires reading its full record, so that path does not add the separate full-product-information charge; the extra charge applies when full product information is turned on for products discovered through Search mode or category links. The **Pricing** tab shows the current rates for your plan tier. Use **Max items** to cap the cost of any run.

#### Is it legal to scrape Walgreens?

This actor collects only publicly available catalog and review data from Walgreens' website. You are responsible for how you use it: follow Walgreens' terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Product names, prices and availability are generally facts, but images, descriptions and review text may be subject to third-party rights.

#### Can I get only new or changed products on a schedule?

Yes. Schedule the actor from the **Schedules** tab and turn on **Track changes across runs**. Each scheduled run then returns only new, updated, reappeared, and, with **Include disappeared products** on, expired records for the same mode, sources, filters and enrichment options. Unchanged products are not billed unless **Include unchanged products** is on.

#### Why is price empty for some products?

Walgreens marks some products as "Priced Per Store" instead of showing one online price. These rows are kept with a null catalog price rather than a guessed number, and the original pricing message from Walgreens stays in the record. In Search mode, a minimum or maximum price filter needs a price to compare, so these products are left out when either price filter is set.

#### Why did my run fail instead of returning an empty dataset?

If a category, search or product page cannot be read (temporary refusals are retried first), the run stops with an error instead of quietly returning an empty or partial dataset for that source, so "nothing found" is never confused with "the catalog could not be read". The same applies when a requested brand or product type does not exist for a search term. Products saved before the failure stay in the dataset, but a failed run does not update the recurring-run baseline. Optional full product information and review lookups are more tolerant: once they fail repeatedly within a run, the actor keeps the base catalog data and stops trying to enrich further products in that run, rather than failing outright.

#### Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to send a condensed product summary to Notion, Linear or Airtable while the complete record stays in the dataset.

### 🔗 More scrapers you might like

Pair this actor with these related scrapers from the same team:

<table>
<tr><td>🛒 <a href="https://apify.com/abotapi/chemistwarehouse-com-au-scraper"><b>Chemist Warehouse AU</b></a><br>Scrape chemistwarehouse.com.au products with prices, RRP, discounts, stock, images...</td><td>🛒 <a href="https://apify.com/abotapi/officeworks-scraper"><b>Officeworks Scraper</b></a><br>Scrape Officeworks products by keyword, category, or URL. Extract names, brands, prices...</td></tr>
<tr><td>🛒 <a href="https://apify.com/abotapi/costco-au-scraper"><b>Costco AU Scraper</b></a><br>Scrape Costco.com.au products with full details and customer reviews. Search by keyword...</td><td>🥦 <a href="https://apify.com/abotapi/woolworths-au-scraper"><b>Woolworths AU Scraper</b></a><br>Scrape Woolworths Australia (woolworths.com.au) grocery products and reviews. Search by...</td></tr>
<tr><td>🧩 <a href="https://apify.com/abotapi/gopuff-prices-assortment-scraper"><b>Gopuff Scraper</b></a><br>Scrape Gopuff, the US quick-commerce delivery store, by location or product: prices...</td><td>🛒 <a href="https://apify.com/abotapi/dm-de-scraper"><b>dm.de</b></a><br>Scrape dm-drogerie markt (dm.de) products: current + strike-through Ausverkauf price with...</td></tr>
</table>

👉 [Browse all abotapi scrapers](https://apify.com/abotapi)

### 💬 Support & custom scrapers

- 🐞 **Found a bug or a missing field?** Open a ticket on the [Issues tab](https://apify.com/abotapi/walgreens-com/issues/open). We usually reply within hours.
- 🛠️ **Need another site, extra fields or a private build?** Email <abotapi@proton.me> or message [Telegram @abotapi](https://t.me/abotapi).
- ⭐ **Enjoying it?** A quick review on the actor page helps other users find it.

# Actor input Schema

## `mode` (type: `string`):

Search mode uses keywords, filters and sorting. URL mode uses the supplied links and ignores search inputs.

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

One or more keywords. Used in Search mode only; products from all terms are deduplicated.

## `brands` (type: `array`):

Exact brand names, such as Crest or Colgate. Match any supplied brand. Search mode only.

## `productTypes` (type: `array`):

Exact product type names, such as Toothpaste or Manual Toothbrushes. Search mode only.

## `minPrice` (type: `number`):

Include products with a current price at least this amount. Search mode only.

## `maxPrice` (type: `number`):

Include products with a current price no more than this amount. Search mode only.

## `minRating` (type: `number`):

Include products rated at least this value, from 0 to 5. Search mode only.

## `onlineOnly` (type: `boolean`):

Include products marked in stock online. Search mode only.

## `offersOnly` (type: `boolean`):

Include products with an offer or a discounted sale price. Search mode only.

## `sortBy` (type: `string`):

Ordering applied separately to each search term. Search mode only.

## `urls` (type: `array`):

Category, search-result, or product links. URL mode ignores keyword inputs and search controls; supported filters and ordering already present in the links are retained.

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

Maximum products to save across the selected sources. Set 0 for no product cap.

## `maxPages` (type: `integer`):

Optional page limit per search term or category. Leave blank or use 0 for unlimited pages; Max items is the only default cap.

## `fetchDetails` (type: `boolean`):

Include the full image gallery, descriptions, ingredients, warnings, uses, shipping information, and complete product details.

## `fetchReviews` (type: `boolean`):

Collect individual reviews with text, ratings, dates, public author details, photos, videos, and helpfulness counts.

## `maxReviewsPerProduct` (type: `integer`):

Newest reviews to collect for each product. Set 0 to collect all available reviews. Large review collections increase output size and run time.

## `resumeFromRunId` (type: `string`):

Skip product IDs already saved in an earlier run or dataset.

## `incrementalMode` (type: `boolean`):

Compare products with the previous completed scan of the same mode, sources, filters, and enrichment options.

## `stateKey` (type: `string`):

Optional custom baseline name. Each mode, source set, filter and enrichment configuration has its own baseline.

## `emitUnchanged` (type: `boolean`):

Save unchanged products during recurring scans.

## `emitExpired` (type: `boolean`):

Save an expired row for a product missing from a completed scan of the same scope.

## `proxy` (type: `object`):

Optional Apify connection settings for collection requests.

## `mcpConnectors` (type: `array`):

Optionally send results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize one under Apify, Settings, API & Integrations, then select it here. Notion gets a page per product; other connectors get a best-effort write or digest. Each connector receives a condensed summary per product, not the full record; the complete record always stays in the dataset. Leave empty to skip; this never changes the dataset output. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com).

## `notionParentPageUrl` (type: `string`):

URL or id of the Notion page under which product pages are created. Required to enable the Notion export; ignored by other connectors.

## `maxNotifyListings` (type: `integer`):

Cap on products written to each connector per run. Does not affect the dataset.

## Actor input object example

```json
{
  "mode": "search",
  "searchQueries": [
    "toothpaste"
  ],
  "onlineOnly": false,
  "offersOnly": false,
  "sortBy": "relevance",
  "urls": [
    "https://www.walgreens.com/store/store/category/productlist.jsp?N=20003053"
  ],
  "maxItems": 20,
  "fetchDetails": false,
  "fetchReviews": false,
  "maxReviewsPerProduct": 20,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "proxy": {
    "useApifyProxy": false
  },
  "maxNotifyListings": 50
}
```

# Actor output Schema

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

No description

## `reviews` (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 = {
    "mode": "search",
    "searchQueries": [
        "toothpaste"
    ],
    "sortBy": "relevance",
    "urls": [
        "https://www.walgreens.com/store/store/category/productlist.jsp?N=20003053"
    ],
    "maxItems": 20,
    "proxy": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/walgreens-com").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 = {
    "mode": "search",
    "searchQueries": ["toothpaste"],
    "sortBy": "relevance",
    "urls": ["https://www.walgreens.com/store/store/category/productlist.jsp?N=20003053"],
    "maxItems": 20,
    "proxy": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/walgreens-com").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 '{
  "mode": "search",
  "searchQueries": [
    "toothpaste"
  ],
  "sortBy": "relevance",
  "urls": [
    "https://www.walgreens.com/store/store/category/productlist.jsp?N=20003053"
  ],
  "maxItems": 20,
  "proxy": {
    "useApifyProxy": false
  }
}' |
apify call abotapi/walgreens-com --silent --output-dataset

```

## MCP server setup

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

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/Bjq4KJfWsyOQZXW2M/builds/f2J7QsQjeQpcbEspm/openapi.json
