# PrestaShop · Catalog Copy by Store URL (`corent1robert/prestashop-catalog-copy`) Actor

Copy a public PrestaShop catalog into another shop: titles, photos, descriptions, SKUs and features. Optional webservice reimport. No admin login on the source. Export-ready rows.

- **URL**: https://apify.com/corent1robert/prestashop-catalog-copy.md
- **Developed by:** [Corentin Robert](https://apify.com/corent1robert) (community)
- **Categories:** E-commerce, Other
- **Stats:** 2 total users, 1 monthly users, 80.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.95 / 1,000 product exporteds

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?

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

## PrestaShop · Catalog Copy by Store URL

Copy a **public PrestaShop catalog** into a clean dataset — titles, photos, descriptions, SKUs and features — and optionally **reimport** those products into another PrestaShop with a webservice key.

**No login on the source shop. No back-office access. Destination key only if you turn reimport on.**

Built for: agencies migrating shops · merchants cloning a catalog · merchandising / competitor snapshots · ops teams who need a spreadsheet first

### Who is this for?

| You are… | Typical goal | Suggested setup |
|----------|--------------|-----------------|
| Agency migrating a client | Move products from shop A to shop B | Source URL + reimport on, with the client’s webservice key |
| Merchant opening a second shop | Clone names, photos and SKUs | Cap 25 first, then `maxProducts` = 0 |
| Merchandising / research | Competitor prices and photos | Export only (reimport off) |
| Ops / PIM | Spreadsheet or JSON feed | Default run, then export CSV |

**What you get by default** — one row per product: name, reference (SKU), tax-included price, short and long description, feature lines, image URLs.

**When to turn reimport on** — you already have a destination PrestaShop and a webservice key with products, images and stock. The Actor upserts by **reference**. Combinations (sizes/colors as variants) are **not** fully cloned in this version: they land as a **simple product**, with features appended to the description.

### Quick start

1. Open the Actor in [Apify Console](https://console.apify.com).
2. Paste the **public home URL** of the PrestaShop you want to copy **from** (the page customers see — not `demo.prestashop.com`, which only launches a demo).
3. Leave **Product cap** at 25 for a first try (empty, `null`, or **0** for the full catalog).
4. Leave **Reimport** off unless you are ready to write into another shop.
5. Click **Start**. Download JSON or CSV from the dataset.

### Ready-made examples (published tasks)

| Example | Best for |
|---------|----------|
| [Export a PrestaShop catalog from the store URL](https://apify.com/corent1robert/prestashop-catalog-copy/examples/export-prestashop-catalog-by-store-url) | First export, capped sample |
| [PrestaShop product sample for a test import](https://apify.com/corent1robert/prestashop-catalog-copy/examples/prestashop-product-sample-test) | Check fields before a full run |
| [Copy a PrestaShop catalog into another shop](https://apify.com/corent1robert/prestashop-catalog-copy/examples/copy-prestashop-catalog-into-another-shop) | A → B with a webservice key |
| [PrestaShop competitor catalog snapshot](https://apify.com/corent1robert/prestashop-catalog-copy/examples/prestashop-competitor-catalog-snapshot) | Prices and photos, export only |

### What it extracts

| Category | Fields |
|----------|--------|
| Identity | `productName`, `reference`, `ean13`, `sourceProductId`, `sourceUrl` |
| Offer | `priceTaxIncl`, `currency`, `quantity`, `manufacturer`, `categoryName` |
| Content | `productDescription`, `descriptionShort`, `features` |
| Media | `imageUrl`, `images`, `imageCount` |
| Import (optional) | `imported`, `destProductId`, `importAction`, `imagesUploaded`, `importError` |

Missing values on the source stay `null`. Import fields stay empty unless reimport is on. Magento-style storefronts (JSON-LD, `data-price-amount`, SKU in the URL) are filled the same way as Classic PrestaShop.

### Input

| Field | Required | Default | Notes |
|-------|----------|---------|-------|
| `shopUrl` | yes | — | Public storefront home |
| `maxProducts` | no | empty / `0` = no cap | Form prefill is 25. Empty, `null`, or **0** = full catalog (time limit still applies). Free Apify plan: **20 products per run**. |
| `concurrency` | no | `24` | Parallel product pages (max 32). Use 24–32 for thousands of SKUs. |
| `importToShop` | no | `false` | Write to a destination shop |
| `destShopUrl` | if import | — | Destination front URL |
| `destApiKey` | if import | — | Webservice key (secret) |
| `taxRatePercent` | no | `20` | Source prices are usually tax included; destination stores tax-excluded. `0` keeps the number as-is |

**API-only** (not on the Console form): `productUrls` (skip discovery), `verboseLogs`, `categoryId` (default 2), `languageId` (default 1), `taxRulesGroupId` (default 1), `proxyConfiguration`.

#### Export only

```json
{
  "shopUrl": "https://shop.example",
  "maxProducts": 25,
  "importToShop": false
}
```

#### Copy into another shop

```json
{
  "shopUrl": "https://source-shop.example",
  "maxProducts": 0,
  "importToShop": true,
  "destShopUrl": "https://destination-shop.example",
  "destApiKey": "YOUR_WEBSERVICE_KEY",
  "taxRatePercent": 20
}
```

### Output example

```json
{
  "shopUrl": "https://shop.example",
  "sourceUrl": "https://shop.example/2-hummingbird-printed-tshirt.html",
  "sourceProductId": 2,
  "productName": "Hummingbird printed t-shirt",
  "reference": "demo_1",
  "ean13": null,
  "priceTaxIncl": 23.9,
  "currency": "EUR",
  "quantity": 300,
  "manufacturer": "Studio Design",
  "categoryName": "Men",
  "imageUrl": "https://shop.example/img/p/1/1.jpg",
  "imageCount": 2,
  "images": ["https://shop.example/img/p/1/1.jpg"],
  "features": ["Composition: Cotton", "Property: Short Sleeve"],
  "imported": false,
  "destProductId": null,
  "importAction": null,
  "scrapedAt": "2026-08-24T12:00:00.000Z"
}
```

### How it works

1. Opens the public home page and checks it looks like PrestaShop.
2. Collects product URLs from the XML sitemap when it exists, then from category / listing pages on the public storefront.
3. Reads each product page (embedded product JSON, then JSON-LD, then markup).
4. Writes one dataset row per product as soon as it is parsed.
5. If reimport is on: creates or updates the destination product by **reference**, uploads photos on **create**, and sets stock when the source exposes a quantity.

### Limitations

- **Simple products only on import.** Combinations (size/color) are not recreated as PrestaShop combinations. Features are copied into the description.
- **Not a full shop clone.** Modules, related products, layered navigation, specific prices, carriers and CMS pages are out of scope.
- **Tax.** Front-office prices are usually tax included. Import converts with `taxRatePercent` (default 20%). Align `categoryId` / `taxRulesGroupId` with your destination catalog if you use non-default groups.
- **Photos on update.** Existing destination products are updated (name, texts, price) without re-uploading images, to avoid duplicates.
- **Source must be public PrestaShop.** Shopify, WooCommerce and custom stacks fail fast with a clear error.
- **Official PrestaShop live demo launcher** (`demo.prestashop.com`) is not a catalog. Paste a real public shop URL. The Console prefill is a public Classic demo shop so Try works without extra setup.

### How much does it cost to copy a PrestaShop catalog?

HTTP-only (no browser). You pay Apify compute plus pay-per-event:

| Scenario | Events | Approx. list price |
|----------|--------|-------------------|
| 25 products, export only | 25 × product row | ~$0.02 |
| 1,000 products, export only | 1,000 × product row | ~$0.95 |
| 1,000 products, with reimport | 1,000 rows + 1,000 imports | ~$4.95 |

`product-row` = **$0.00095** (~$0.95 per 1,000) — same ballpark as other public catalog scrapers. Reimport is the extra: **$0.004** per product actually written to the destination shop. Failed pages and skipped imports are not billed. No actor-start fee. Compute stays low on datacenter proxy.

### Is it legal to scrape PrestaShop?

This Actor only reads data the source shop already shows to any visitor. You are responsible for complying with the shop’s terms, GDPR and any licence on product photos or texts — especially if you reimport into a commercial shop. Do not copy catalogs you do not have rights to reuse.

### Also available

**[Shopify Catalog · Products by Store URL](https://apify.com/corent1robert/shopify-products-scraper)** — export a public Shopify catalog (one row per variant).

**[PrestaShop Addons · Publisher Emails](https://apify.com/corent1robert/prestashop-addons-unique-authors)** — unique Addons publishers and contact emails (leads, not catalogs).

### Local development

```bash
cd prestashop-catalog-copy
npm install
## storage/key_value_stores/default/INPUT.json must include shopUrl
## or: apify run --input-file=./input.json
apify run
npm test
```

`storage/` is local only and is not uploaded (`apify push`). Cloud input overwrites keys from repo `input.json`.

### Support

Contact <corentin@outreacher.fr> if you need combinations cloned, a custom mapping, or a scheduled A → B sync.

# Actor input Schema

## `shopUrl` (type: `string`):

Home page customers already see — not the back office, and not the demo.prestashop.com launcher. The Actor checks it looks like PrestaShop before reading products.

## `maxProducts` (type: `integer`):

Stop after this many products. Leave empty, `null`, or **0** for the full catalog (the run still stops at the time limit). Prefill 25 is only a first-try sample.

## `concurrency` (type: `integer`):

Max parallel product pages (the run starts at 8 and ramps up only if the shop holds). 32 at once often times out on Magento/WAF shops.

## `importToShop` (type: `boolean`):

Create or update products on your shop by SKU (reference). Off = spreadsheet / JSON export only.

## `destShopUrl` (type: `string`):

Your PrestaShop front URL (the shop that should receive the catalog).

## `destApiKey` (type: `string`):

Key from Advanced Parameters → Webservice. Needs products, images and stock. Never share it in public task pages.

## `taxRatePercent` (type: `number`):

Source prices are usually tax included. The destination stores tax-excluded prices. Default 20 (France). Set 0 to keep prices as-is.

## Actor input object example

```json
{
  "shopUrl": "https://shop.clayrtons.com",
  "maxProducts": 8,
  "concurrency": 8,
  "importToShop": false,
  "taxRatePercent": 20
}
```

# Actor output Schema

## `dataset` (type: `string`):

Full export — one product per row.

## `catalogOverview` (type: `string`):

Name, SKU, price, photo and source URL.

## `importStatus` (type: `string`):

Whether each product was created or updated on the destination shop.

## `runLog` (type: `string`):

Text log mirrored from the run console.

# 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 = {
    "shopUrl": "https://shop.clayrtons.com",
    "maxProducts": 8
};

// Run the Actor and wait for it to finish
const run = await client.actor("corent1robert/prestashop-catalog-copy").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 = {
    "shopUrl": "https://shop.clayrtons.com",
    "maxProducts": 8,
}

# Run the Actor and wait for it to finish
run = client.actor("corent1robert/prestashop-catalog-copy").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 '{
  "shopUrl": "https://shop.clayrtons.com",
  "maxProducts": 8
}' |
apify call corent1robert/prestashop-catalog-copy --silent --output-dataset

```

## MCP server setup

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

```

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/qiDF4WWyi6odmJzyv/builds/lhbIY0v0ORdpXu7tE/openapi.json
