# WooCommerce Catalog Export (`jj_toolworks/woocommerce-catalog-export`) Actor

Export public WooCommerce Store API products with currency-aware prices, bounded variation details, source links, deduplication, and catalog completeness reports.

- **URL**: https://apify.com/jj_toolworks/woocommerce-catalog-export.md
- **Developed by:** [JJ Toolworks](https://apify.com/jj_toolworks) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$3.00 / 1,000 complete product with variants

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

## WooCommerce Catalog Export

Export the public product catalog exposed by a WooCommerce Store API. Receive product records, available variation details, source links and a summary for every input. Prices preserve the source currency and its declared number of decimal places.

Useful workflows include agency catalog audits, supplier assortment checks, published product-feed preparation and comparisons across Shopify and WooCommerce stores. Category/search presets support specialty retail, parts, craft supplies, home goods, food and construction suppliers using the same output contract.

### Start with a small source

```json
{
  "start_urls": ["https://scrapeme.live"],
  "max_products_per_source": 5,
  "max_products": 5
}
```

Replace the example with your source store. API availability varies by store and can change. For WordPress installed in a subdirectory, include that path in the store URL. The Actor also accepts a standard `/product/slug` URL or the Store Products API endpoint.

| Input | Meaning |
| --- | --- |
| `start_urls` | 1–20 public WooCommerce source URLs |
| `max_products_per_source` | Per-input assessment cap; default 50, maximum 1,000 |
| `max_products` | Unique exported products across the run; default 100, maximum 2,000 |
| `category` | Optional public category IDs or slugs, comma-separated |
| `search` | Optional search text passed to the Store API |
| `expected_currency` | Optional three-letter code; mismatching products are incomplete and have no success event |

The filters use the source API's behavior. They do not introduce a private category index or normalize taxonomies across unrelated stores.

### Practical presets

The Scrapeme examples use a public demonstration catalog. The Nalgene example uses a public manufacturer catalog. They demonstrate the workflow and do not imply affiliation with either site. These filtered source requests returned data in read-only checks on October 10, 2026; the recorded cloud smoke test covers the unfiltered five-product Scrapeme sample above.

#### Agency or category audit

Start with a small, named assortment to inspect SKU, price, description and link mappings. The demo category `seed` returned four public simple products at the source check.

```json
{
  "start_urls": ["https://scrapeme.live"],
  "category": "seed",
  "max_products_per_source": 5,
  "max_products": 5,
  "expected_currency": "GBP"
}
```

For a client store, replace the root and use that store's actual category ID or slug. Category IDs belong to a particular store; do not carry a demo ID into a different store. Keep `category`, `search` and currency expectations consistent when comparing two snapshots.

#### Outdoor-retail supplier snapshot

This preset requests a small slice of Nalgene's public bottle category using the source API's search behavior. The checked response contained five simple USD products. A five-product limit creates a sample, so its source summary is expected to be truncated when more products match.

```json
{
  "start_urls": ["https://nalgene.com"],
  "category": "bottles",
  "search": "Ultralite",
  "max_products_per_source": 5,
  "max_products": 5,
  "expected_currency": "USD"
}
```

Reuse the pattern for construction supplies, replacement parts, craft materials or specialty food by supplying an accessible WooCommerce store and its own categories or search terms. API search is a text filter; it does not establish that two items are interchangeable.

#### Known-product price watch

Use a public Store API product ID when your watchlist is already known. This avoids depending on a merchant's custom storefront permalink structure. The demo below returned one simple product in the source check.

```json
{
  "start_urls": ["https://scrapeme.live/wp-json/wc/store/v1/products/729"],
  "max_products_per_source": 1,
  "max_products": 1,
  "expected_currency": "GBP"
}
```

Use the `product_id` from a previous export with the same source's Store API path. For a larger curated list, supply up to 20 product API URLs and set an appropriate run cap. URL query filters are not imported; put supported `category` and `search` values in their input fields.

### Output

The default dataset uses `row_type` values `product`, `variant`, `summary`, `product_error` and `exports`. Product rows include nested variants. The final `exports` row provides links to `PRODUCTS.json`, `VARIANTS.json` and `SUMMARIES.json`.

Each product includes its ID, title, public link, SKU when published, description, price, currency, availability, included images and retrieval time. Variant rows include the parent product key and their own ID, SKU and price. `currency_minor_unit` controls the price scale: for example, a JPY value with scale 0 remains a whole-unit amount, while USD scale 2 is divided by 100. No exchange-rate conversion occurs.

`status` and `reasons` explain product completeness. A source summary reports the number of completed, incomplete and duplicate products and whether its listing enumeration finished. A complete individual product can appear in a truncated store scan when the user-selected limit is reached.

### Move a snapshot into a spreadsheet or comparison workflow

Download `PRODUCTS.json` from the final exports row. Keep one row per product; use `VARIANTS.json` separately when you need one row per included option. This optional `jq` command creates a compact CSV from complete products:

```sh
jq -r '(["product_key","sku","title","currency","price","available","product_url","fetched_at"], (.[] | select(.status == "complete") | [.product_key,.sku,.title,.currency,.price,.available,.product_url,.fetched_at])) | @csv' PRODUCTS.json > catalog.csv
```

| Workflow | Keep these fields | Comparison rule |
| --- | --- | --- |
| Agency catalog audit | `product_key`, `sku`, `title`, `description`, `product_url`, `status` | Check field presence and mapping; an unpublished SKU can legitimately be empty |
| Supplier price watch | `product_key`, `currency`, `price`, `available`, `fetched_at` | Compare the same product and currency across successful observations |
| Category assortment review | Product identity, `categories`, input filters and source summary | Only infer disappearance when both source enumerations finished successfully with the same filters |
| Variant review | `product_key`, `variant_id`, `sku`, `options`, `price`, `product_status` | Exclude incomplete parent products from an automatic complete-variant comparison |

The Actor creates snapshots. Cross-run differences, notifications, scheduled tasks and destination spreadsheets are configured downstream. Retain the last successful snapshot if a refresh fails. Preserve the currency column and decimal strings rather than combining unlike currencies in a numeric price column.

### Pricing unit

One success event is one distinct complete public product per store and currency in the run, including up to 100 public variations when needed. See the Pricing tab for the current rate. Duplicate inputs or product IDs do not add success events.

An option-bearing product is incomplete when its public variation details are missing, capped, invalid or cannot be verified as complete. Password-protected/redacted products and records with invalid currency or monetary data are incomplete. Incomplete products and failed fetches have no success event; the available fields are still returned when possible.

### Boundaries and limits

This Actor uses the unauthenticated `/wp-json/wc/store/v1/products` endpoint. It does not request private orders, customers or unpublished merchandise, submit product passwords, or use merchant credentials. The source may redact protected descriptions.

At most one supplementary variation request is made per option-bearing product, with 100 included child records. Responses are limited to 2 MB, and each input source has a 180-second work limit. Large runs also remain subject to platform-wide output and request limits. Use smaller batches when products have extensive descriptions or many variations.

Catalog requests use a page size bounded by the selected product caps, up to 100. A five-product source cap therefore requests five catalog records per page. The chosen size stays fixed within that source's scan so pagination offsets remain consistent; variation requests retain their separate 100-record bound.

Store API support and visibility vary by store, plugins and configuration. A completed export covers the visible public API response for the selected filters, not the store's entire private catalog. A public stock flag does not guarantee local shipping availability or exact inventory. A truncated or failed refresh must not be interpreted as product removal.

### Reuse the same workflow

Save separate tasks for source stores or categories, then keep those filters stable across runs. Map `product_id`, `sku`, `currency`, `price` and `product_url` into your downstream spreadsheet or comparison system. Exact identifiers are preferable to assuming that similar product names represent the same item.

For help with a public source, provide the input URL, run ID and returned reason. Do not include store credentials.

### Price and run controls

The launch price is **$3 per 1,000 completed units** ($0.003 per event), as defined above. Check the current Pricing tab before running. Status and duplicate rows do not add this custom event. Set a maximum charge appropriate for your batch; a run stops when its event budget is exhausted. `RUN-SUMMARY` records actual accepted events and execution totals.

Automatic replay of an interrupted run is disabled to prevent duplicate charges. Keep the available output, then start a new run for a new execution. A later run is a new billable execution. Completed dataset rows and individually saved files remain available when a budget stops a run. Combined exports, manifests, and snapshots assembled at the end may be absent after a budget stop or interruption; use a sufficient run budget when you need those aggregate files. The initial release uses documented input limits and public source access; external source changes can require maintenance.

# Actor input Schema

## `start_urls` (type: `array`):

Public store roots, a /product/slug URL, or the public Store Products API endpoint. Include a WordPress subdirectory if applicable.

## `max_products_per_source` (type: `integer`):

Maximum public product records assessed for each input source. A cap produces a truncated source summary and bounds the catalog request page size.

## `max_products` (type: `integer`):

Maximum unique exported products across all inputs, including incomplete products.

## `expected_currency` (type: `string`):

Optional three-letter currency code. Mismatching products are incomplete and have no success event. This does not perform currency conversion.

## `category` (type: `string`):

Category IDs or slugs, comma-separated, passed to the public Store API.

## `search` (type: `string`):

Text search applied by the source Store API.

## Actor input object example

```json
{
  "start_urls": [
    "https://scrapeme.live"
  ],
  "max_products_per_source": 5,
  "max_products": 5
}
```

# Actor output Schema

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

No description

## `summary` (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 = {
    "start_urls": [
        "https://scrapeme.live"
    ],
    "max_products_per_source": 5,
    "max_products": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("jj_toolworks/woocommerce-catalog-export").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 = {
    "start_urls": ["https://scrapeme.live"],
    "max_products_per_source": 5,
    "max_products": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("jj_toolworks/woocommerce-catalog-export").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 '{
  "start_urls": [
    "https://scrapeme.live"
  ],
  "max_products_per_source": 5,
  "max_products": 5
}' |
apify call jj_toolworks/woocommerce-catalog-export --silent --output-dataset

```

## MCP server setup

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

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/A6O0uOAbnaFT9sc23/builds/wMoBA5smE06SugPfe/openapi.json
