# Macy's Product Scraper (`mrdoe/macys-product-scraper`) Actor

Scrape macys.com products, prices, brands, categories, product details, ratings, images and availability into clean, structured data. Affordable and easy to use for ecommerce research, price monitoring, competitor analysis and product intelligence.

- **URL**: https://apify.com/mrdoe/macys-product-scraper.md
- **Developed by:** [MrDoe](https://apify.com/mrdoe) (community)
- **Categories:** E-commerce, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 results

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

### What does Macy's Product Scraper do?

**Macy's Product Scraper** extracts product data from [Macys.com](https://www.macys.com) - keyword search results and full product detail pages - **anonymously, no login, no Macy's account, no API key**. Two operations live in one actor: search for products by keyword, or look up full detail for one or many product IDs.

Macy's server-renders its site as a Nuxt 3 app and embeds the exact structured data (price, rating, stock, images, breadcrumbs) that powers its own product cards as JSON in every page. This Actor reads that embedded JSON directly instead of scraping visible text, so extraction stays accurate even as visual page markup changes.

### Why use this Actor?

- **Price tracking** - schedule `productDetails` on a cron and diff consecutive runs to catch sales and restocks.
- **Market research / assortment mapping** - `search` gives you ranked results for any keyword, with price, rating, review count, and sale/discount info.
- **Batch, one start fee** - pass a list of keywords or product IDs and one run covers all of them.

### How to use it

1. Pick an **Operation**: Product Search or Product Details.
2. Fill the matching field:
   - **Search** → `query` (e.g. `shoes`) or `queries` for a batch.
   - **Product Details** → `productId` (e.g. `25155177`) or a full product URL, or `productIds` for a batch.
3. Optionally set `sortBy`.
4. Click **Start**.

There is no page cap on `search` - it always follows a query through to Macy's own last reported page (read directly from the site's own pagination metadata, not estimated). Batch a lot of keywords and this can produce a very large run; that's intentional, not a bug.

Batch fields (`queries`/`productIds`) win over their singular counterparts when filled; duplicates and blanks are dropped automatically.

### Input

| Field                      | Type              | Description                                                                                                                    |
| -------------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `operation`                | string (required) | One of: `search`, `productDetails`.                                                                                            |
| `query` / `queries`        | string / array    | Search keyword(s). Required by `search`.                                                                                       |
| `productId` / `productIds` | string / array    | A Macy's numeric product ID (e.g. `25155177`) or a full product URL. Used by `productDetails`.                                 |
| `sortBy`                   | string            | `ORIGINAL` (default), `PRICE_LOW_TO_HIGH`, `PRICE_HIGH_TO_LOW`, `TOP_RATED`, `BEST_SELLERS`, `NEW_ITEMS`. Applies to `search`. |
| `proxyConfiguration`       | object            | A residential proxy is strongly recommended for sustained volume.                                                              |

### Why no ZIP code / session priming?

Unlike some large retailers, a plain, cookie-less request to Macy's search and product pages already returns real prices and stock status - live-verified 2026-08-24 on multiple categories (shoes, blenders) with no cookies set at all. So this Actor skips the session-priming step some other retail scrapers need.

### Product ID lookup

Macy's product URLs look like `/shop/product/{cosmetic-slug}?ID={id}` - only the numeric `ID` matters. A request with any slug and a real ID 301-redirects to the canonical URL for that ID (live-verified 2026-08-24: a nonsense slug + a real ID still landed on the correct product). So `productId`/`productIds` accepts either a bare ID or a full URL; the slug in a pasted URL doesn't need to be exact.

### Output

One flat row per item. Search rows carry search-result fields; product-detail rows carry the full page (description, bullet points, available colors/sizes, category breadcrumb). Every row has `_operation` (which mode produced it) and `status` (`success` or `error`) so you can split/filter a mixed export.

Search row example:

```json
{
    "_operation": "search",
    "productId": "25155177",
    "title": "Women's Mavis High Top Wedge Sneakers",
    "brand": "Steve Madden",
    "price": 159,
    "listPrice": null,
    "onSale": false,
    "percentOff": null,
    "currency": "USD",
    "rating": 4.6,
    "reviewCount": 176,
    "available": true,
    "colorCount": 8,
    "image": "https://slimages.macysassets.com/is/image/MCY/products/8/optimized/35037348_fpx.tif?qlt=80",
    "productUrl": "https://www.macys.com/shop/product/steve-madden-womens-mavis-high-top-lace-up-wedge-sneakers?ID=25155177",
    "query": "shoes",
    "status": "success"
}
```

Product detail row example:

```json
{
    "_operation": "productDetails",
    "productId": "25155177",
    "title": "Women's Mavis High Top Wedge Sneakers",
    "brand": "Steve Madden",
    "description": "...",
    "bulletText": ["Wedge heel: 1\"", "Round toe", "Hook-and-loop closure"],
    "price": 159,
    "listPrice": 179,
    "onSale": false,
    "currency": "USD",
    "rating": 4.6,
    "reviewCount": 176,
    "ratingBreakdown": [{ "rating": 5, "count": 136, "percentage": 77.27 }],
    "available": true,
    "colors": ["Taupe Suede", "Black Suede", "White Suede Multi"],
    "sizes": ["5M", "5.5M", "6M"],
    "images": ["https://slimages.macysassets.com/..."],
    "categories": ["Women's Fashion, Shoes & Accessories", "Athletic & Sneakers"],
    "productUrl": "https://www.macys.com/shop/product/steve-madden-womens-mavis-high-top-lace-up-wedge-sneakers?ID=25155177",
    "status": "success"
}
```

### Pricing

This Actor uses pay-per-event pricing - one small run-start charge, then a per-row charge for each search result or product-detail lookup. See the **Pricing** tab for current rates. Failed lookups land as `status: "error"` rows and are never charged. There is no page cap - `search` always runs to Macy's own last reported page for each keyword, so keep your batch size (number of keywords/IDs) in mind to bound spend on a given run.

### Limitations

- Only the numbers/text Macy's shows to an anonymous, logged-out visitor are available - no member-only pricing.
- Customer reviews are not part of this Actor - see the companion **Macy's Review Scraper**.
- `minPrice`/`maxPrice` and category-ID filtering are not exposed as inputs: Macy's price-range facet path (`/shop/search/Price/{min}|{max}`) did not reliably narrow results in live testing (2026-08-24), and category browsing uses a different URL scheme per department that wasn't independently verified end-to-end this session. Keyword search plus `sortBy` cover the differentially-verified path.
- US site (macys.com) only in this version.
- Macy's page markup/JSON structure can change over time; extraction reads the site's own embedded Nuxt hydration payload (the same data structure that renders the visible page), which is more stable than CSS selectors but not immune to a backend redesign.

### FAQ

**Does Macy's have a public API?** Not one that's open to general scraping/reseller use. This Actor gets you search and product data anonymously, no approval process.

**Do I need a Macy's account or API key?** No - it runs entirely against Macy's public, logged-out web pages.

**A run returns 0 results with no error - why?** An unusually narrow keyword can legitimately return nothing, or a run mid-way through a large batch can occasionally hit a rate-limited session - a residential proxy handles this automatically in most cases.

### Disclaimer

This Actor is an independent tool, not affiliated with or endorsed by Macy's, Inc. It only accesses data Macy's serves publicly to anonymous visitors. Use it in compliance with Macy's Terms of Use and applicable law in your jurisdiction. Found a bug or have a feature request? Use the Issues tab on this Actor's page.

# Actor input Schema

## `operation` (type: `string`):

Which Macy's data to scrape. One operation per run.

## `query` (type: `string`):

Keyword to search Macy's, e.g. "shoes". Used by the search operation. Defaults to a demo query if left blank.

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

Many keywords in one run. Wins over "query" when filled. Duplicates and blanks are dropped.

## `productId` (type: `string`):

A Macy's numeric product ID (e.g. "25155177") or a full product URL (e.g. "https://www.macys.com/shop/product/...?ID=25155177"). Used by the productDetails operation. Defaults to a demo product if left blank.

## `productIds` (type: `array`):

Many product IDs or product URLs in one run. Wins over "productId" when filled.

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

Applies to search.

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

A residential proxy is strongly recommended for sustained volume.

## Actor input object example

```json
{
  "operation": "search",
  "query": "shoes",
  "productId": "25155177",
  "sortBy": "ORIGINAL",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `overview` (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 = {
    "query": "shoes",
    "productId": "25155177"
};

// Run the Actor and wait for it to finish
const run = await client.actor("mrdoe/macys-product-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 = {
    "query": "shoes",
    "productId": "25155177",
}

# Run the Actor and wait for it to finish
run = client.actor("mrdoe/macys-product-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 '{
  "query": "shoes",
  "productId": "25155177"
}' |
apify call mrdoe/macys-product-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,mrdoe/macys-product-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/zaUgmjLQ99YXcOal2/builds/FRvzfdjg9jILc5ozR/openapi.json
