# Fruugo Scraper - Products, Prices, Sellers & GTIN/EAN (`abotapi/fruugo-com-scraper`) Actor

Scrape Fruugo marketplace products by keyword or URL across country storefronts. Extract product names, prices, currencies, merchants, seller counts, GTIN/EAN product identifiers and images.

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

## Pricing

from $1.60 / 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

## Fruugo Scraper: Products, Prices and Sellers

Fruugo Scraper turns Fruugo into a clean product data API. Search the marketplace by keyword or paste product links, and get titles, brands, prices with currency, list prices and discounts, merchant names, seller counts, shipping costs, stock state, GTIN/EAN codes, descriptions, attributes and image galleries, priced the way local shoppers see them. Then export to JSON, CSV or Excel, or pull the results straight into your app through the API.

### Why This Scraper?

- **Two ways in.** Search by keyword, or paste Fruugo product and search links. No need to build URLs by hand.
- **Country storefront pricing.** Prices, currency, merchant offers and availability are served per country. The Australian storefront is verified end to end; the United Kingdom storefront also serves and is offered on the same basis. Every storefront sits behind the same protective challenge whose availability opens and closes in short windows, Australia included: a closed window fails the run loudly instead of returning an empty dataset, and a retry a few minutes later usually lands in an open window.
- **Seller depth on demand.** Switch product details on for the merchant name, shipping cost, stock state, GTIN/EAN, description, attributes and the full image gallery, and pay the surcharge only for what you enrich.
- **Discounts included.** List price and discount percent ride on every enriched row, ready for price monitoring and MAP tracking.
- **GTIN/EAN on every enriched row.** Join Fruugo rows with your other retail datasets on the barcode.
- **Built for schedules.** Incremental mode returns only new and changed products on recurring runs, and a refused run fails loudly instead of returning an empty dataset.

### Use Cases

- **Local-market pricing:** read the catalogue at Australian shopper prices, with currency, merchant offers and availability exactly as local shoppers see them.
- **Brand and MAP monitoring:** track list prices, discounts and merchant offers per product over time.
- **Dropshipping and sourcing research:** find merchants, seller counts and shipping costs behind any listing.
- **Catalog enrichment:** fill GTIN/EAN codes, descriptions, attributes and image galleries into your own product database.
- **Market analytics and data science:** build historical price and availability datasets for modelling.

### Data You Get

> Sample shape: values are illustrative placeholders, not from a live record.

| Field | Example |
| --- | --- |
| `recordId` | `"fruugo:AU:307014223"` |
| `url` | Fruugo link to the product |
| `productId` / `skuId` / `fruugoId` | `"307014223"` / `"687617615"` / `"307014223-687617615"` |
| `title` | `"Sample Eye Drops 15ml"` |
| `brand` | `"Sample Brand"` |
| `category` / `breadcrumbs` | `"Eye Drops"` / `"Shop > Health > Eye Drops"` |
| `price` / `priceCurrency` / `priceText` | `18.95` / `"AUD"` / `"From $18.95"` |
| `listPrice` / `discountPercent` | `34.95` / `28.6` |
| `availability` / `inStock` | `"In Stock"` / `true` |
| `merchantName` | `"Sample Merchant"` |
| `sellerCount` | `4` |
| `shippingPrice` / `shippingText` | `15.99` / `"+ $15.99 Shipping"` |
| `description` | `"Sample product description."` |
| `ean` / `gtin` / `sku` | `"9312345678901"` / `"9312345678901"` / `"687617615"` |
| `imageUrl` / `imageUrls` | cover image / full gallery |
| `attributes` | `["Age Group: kids", "Gender: male"]` |
| `returnDays` | `14` |
| `country` | `"AU"` |
| `changeType` / `changedFields` / `firstSeenAt` / `lastSeenAt` | incremental mode only |

Card fields (title, brand, price, seller count, link) are on every row either way. Detail fields (description, merchant, shipping, stock, GTIN/EAN, gallery, attributes, return terms) need Fetch product details.

### How to Use

1. Pick a **mode**: `search` (by keyword) or `url` (paste links).
2. Pick the **country storefront** whose prices you want.
3. Leave **Fetch product details** on for the full row, or switch it off for a fast crawl.
4. Set **Max items** to control run size and cost, then click **Start**.
5. Download the dataset as JSON, CSV or Excel, or read it through the API.

**Search for a keyword:**

```json
{
  "mode": "search",
  "searchTerms": ["lego"],
  "country": "AU",
  "fetchDetails": true,
  "maxItems": 5
}
```

**One product in full:**

```json
{
  "mode": "url",
  "urls": ["https://www.fruugoaustralia.com/visine-eye-drops-red-eye-comfort-05-oz-15ml/p-307014223"],
  "country": "AU",
  "fetchDetails": true
}
```

**Cheapest first, details on:**

```json
{
  "mode": "search",
  "searchTerms": ["lego"],
  "country": "AU",
  "sort": "prasc",
  "fetchDetails": true,
  "maxItems": 10
}
```

#### Run it from your code

Python:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/fruugo-com-scraper").call(run_input={"mode": "search", "searchTerms": ["lego"], "country": "AU", "maxItems": 5})
for product in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(product["title"], product["price"], product["priceCurrency"])
```

JavaScript:

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

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/fruugo-com-scraper').call({ mode: 'search', searchTerms: ['lego'], country: 'AU', maxItems: 5 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

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

#### Resume and recurring updates

- **Resume** (`resumeFromRunId`) continues one interrupted run: paste its run or dataset ID and the actor skips everything already collected there, so you don't pay twice.
- **Incremental mode** (`incrementalMode`) is for scheduled runs over the same scope. Each record is classified `NEW`, `UPDATED` (with `changedFields`), `UNCHANGED` (suppressed and not billed unless `emitUnchanged` is on), `REAPPEARED` or `EXPIRED` (only after a run that scanned the whole scope, and only with `emitExpired`). `stateKey` names or shares the stored state. Price moves and stock changes ARE reported as `UPDATED`: on a store they are the signal, not noise. With incremental mode off, output is exactly as before. Note the store's search results rotate between runs, so a scheduled incremental run can legitimately classify most rows as `NEW` even when nothing you care about changed.

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

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step **after** the scrape: the Apify dataset is never changed.

**What gets written to the connector:** a condensed, human-readable **summary** of each record, not the full JSON. Each item becomes one entry with a **title** and its key fields flattened to plain text. The **complete record always stays in the Apify dataset**.

1. Authorize a connector once under **Apify → Settings → Integrations** (Notion, Linear, Airtable, or Apify).
2. Select it in the **"Pipe results into your apps"** input field. (If the picker is empty, you haven't authorized a connector yet.)
3. For **Notion**, also set `notionParentPageUrl` to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.

### Input Parameters

| Parameter | Type | Default | Description |
| --- | --- | --- | --- |
| `mode` | string | `search` | `search` or `url`. |
| `searchTerms` | array | `["lego"]` | Keywords to search (search mode). |
| `urls` | array | sample | Fruugo product or search links (url mode). Both product link shapes (`/p-307014223`, `/p-307014223-687617615`) and search links (`/search?q=...`, `&page=N`, a `sorting=` on the link wins for that walk) are accepted, and each link is read on the storefront its host names (a fruugo.co.uk link returns UK-priced rows stamped country GB, whatever the country input says); a Fruugo link whose storefront cannot be mapped fails the run loudly. |
| `country` | string | `AU` | Country storefront: Australia (verified end to end) or the United Kingdom (serves through the same connection handling). Both flap in short windows like every storefront, Australia included; a refused run fails loudly. The United States storefront is not offered yet: it has not been verified. Pasted URL-mode links are honored for the storefront their host names. |
| `sort` | string | `recommended` | Store ordering: `recommended` or `prasc` (price lowest first; sorted cards omit the from-price, details fill it). |
| `minPrice` | number | (none) | Keep rows in this price range (storefront currency). |
| `maxPrice` | number | (none) | Keep rows in this price range (storefront currency). |
| `fetchDetails` | boolean | `true` | Product page read per record (description, merchant, GTIN/EAN, gallery); charged once per record. |
| `maxItems` | integer | `20` | Stop after this many records (`0` = no limit). |
| `maxPages` | integer | `0` | Safety bound on pages per source (`0` = no page limit). |
| `proxy` | object | Apify Proxy | Connection settings. Residential is recommended for large or frequent runs. |
| `resumeFromRunId` | string | (none) | Continue one interrupted run. |
| `incrementalMode` | boolean | `false` | Return only new and changed records on scheduled runs. |
| `stateKey` | string | (none) | Name or share an incremental-mode state. |
| `emitUnchanged` | boolean | `false` | Also return (and bill) unchanged records. |
| `emitExpired` | boolean | `false` | Also return (and bill) expired records. |
| `ignoreFieldsForChanges` | array | (none) | Extra fields to exclude from change detection. |
| `mcpConnectors` | array | (none) | Optional: send a summary of each record to apps you authorized under Integrations. |
| `notionParentPageUrl` | string | (none) | Notion connector only: page under which records are created. |
| `maxNotifyListings` | integer | `50` | Cap on items written to each connector per run. |

### Output Example

> Sample shape: values are illustrative placeholders, not from a live record.

**Enriched product record:**

```json
{
  "recordId": "fruugo:AU:000000000",
  "url": "https://www.fruugoaustralia.com/sample-product/p-000000000",
  "productId": "000000000",
  "title": "Sample Eye Drops 15ml",
  "brand": "Sample Brand",
  "category": "Eye Drops",
  "price": 18.95,
  "priceCurrency": "AUD",
  "listPrice": 24.95,
  "discountPercent": 24.0,
  "availability": "In Stock",
  "inStock": true,
  "merchantName": "Sample Merchant",
  "sellerCount": 2,
  "shippingPrice": 15.99,
  "description": "Sample product description.",
  "ean": "9312345678901",
  "gtin": "9312345678901",
  "imageUrl": "https://img.fruugo.com/product/1/28/0000000000_max.jpg",
  "imageUrls": ["https://img.fruugo.com/product/1/28/0000000000_max.jpg"],
  "attributes": ["Age Group: adult"],
  "returnDays": 14,
  "country": "AU"
}
```

### Plan Requirement

The default proxy setting works out of the box, and the actor rotates connections automatically when one is refused. The storefront is read through ordinary shared connections once the session is established; for large or frequent runs, the residential proxy group gives more headroom and is recommended. If your Apify plan does not include proxy access, the run fails with a clear message instead of returning an empty result; a paid plan with proxy access is required.

### FAQ

#### How much does it cost?

You pay per record returned, with product details billed only when Fetch product details is on. The **Pricing** tab shows the current rates. Use **Max items** to cap the cost of any run.

#### Is it legal to scrape Fruugo?

This actor collects only publicly available marketplace data. You are responsible for how you use it: follow the store terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Prices and availability are generally facts, but photos, descriptions and brand assets 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 **Incremental mode**. Each run then returns only new and updated records, and unchanged ones are not billed.

#### Why did a run return fewer products than Max items?

The walk stops at the natural end of the results. Set a higher Max items, or `0`, to collect the whole scope. Sorted searches return the store order, so a capped run keeps the cheapest rows first.

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

If the store refuses every request, the run stops with a clear message so "nothing matched" is never confused with "nothing could be read". Run it again in a few minutes. If only some sources could be read, you still get what was found.

#### 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 push results into Notion, Linear or Airtable.

### 🔗 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/idealo-de-price-comparison-scraper"><b>Idealo.de</b></a><br>Scrape Idealo.de products with identity details, GTIN, price ranges, specifications...</td><td>🛒 <a href="https://apify.com/abotapi/bigw-marketplace-scraper"><b>BIG W Marketplace Scraper</b></a><br>Scrape BIG W Marketplace seller listings from bigw.com.au: name, brand, price, was-price...</td></tr>
<tr><td>🧩 <a href="https://apify.com/abotapi/miravia-es-scraper"><b>Miravia Spain Scraper</b></a><br>Scrape Miravia Spain by keyword, seller store or URL. Every row carries the selling price...</td><td>🔌 <a href="https://apify.com/abotapi/currys-co-uk"><b>Currys UK Scraper</b></a><br>Scrape Currys UK electronics by keyword or URL. Extract prices, brands, stock status...</td></tr>
<tr><td>🧩 <a href="https://apify.com/abotapi/allegro-pl-scraper"><b>Allegro Scraper</b></a><br>Scrape Allegro by keyword or URL. Extract offers, prices, delivery, seller details, and...</td><td>🧩 <a href="https://apify.com/abotapi/ebay-com-scraper"><b>eBay Scraper</b></a><br>Scrape eBay by keyword, category, seller or pasted link across 16 country storefronts...</td></tr>
</table>

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

### 💬 Support

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

# Actor input Schema

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

How to start the scrape. 'search' runs store searches. 'url' processes the store URLs you paste: a product URL returns that single product in full, and a search URL is paged like a search, its own query deciding the scope. The price bounds apply to the rows this run reads in both modes; a pasted product URL is the one exception and returns that single product in full.

## `searchTerms` (type: `array`):

One or more things to search Fruugo for, for example 'lego', 'vitamins', 'phone case'. Each term is scraped independently. Search mode only: in URL mode the scope is read out of each pasted URL instead.

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

Paste product URLs or search URLs; every link shape the store uses is accepted. Product links end in /p-307014223, or the longer /p-307014223-687617615 offer form. Search links contain /search?q=watch; add \&page=3 to start that walk further in, and a sorting= on the link is honored for that walk when present (otherwise Sort results by below applies). A pasted URL decides its own scope and its own storefront: a product URL returns that one product in full, a search URL is paged like a search, and both are read on the storefront their host names (a fruugo.co.uk link returns UK-priced rows stamped country GB, whatever the Country storefront input says). A Fruugo link whose storefront cannot be mapped fails the run loudly.

## `country` (type: `string`):

Country storefront to scrape: prices, currency, merchant offer and availability are served per country. Australia is verified end to end; the United Kingdom storefront also serves through the actor's connection handling and is offered on the same basis. Every storefront sits behind the same protective challenge whose availability opens and closes in short windows, Australia included: a refused run fails loudly instead of returning an empty dataset, and a retry a few minutes later usually lands in an open window. The United States storefront is not offered yet: recent probe attempts through the shipped connection handling were all refused and it has not been verified. Product and search links pasted in URL mode are honored for the storefront they name (a fruugo.co.uk link walks the UK storefront and returns UK-priced rows); a Fruugo link whose storefront cannot be mapped fails the run loudly instead of returning wrong-country data.

## `sort` (type: `string`):

The store's own server-side ordering, sent with every page of every walk. 'recommended' is the store default and sends no parameter. 'prasc' (price low to high) is verified live: note the store's price-sorted cards omit the from-price line, so keep Fetch product details on to fill the exact price, merchant and currency. Applies in BOTH search mode and URL mode.

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

Only keep rows whose price is at least this amount, in the storefront currency. Applied to the rows this run reads. Applies in BOTH search mode and URL mode.

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

Only keep rows whose price is at most this amount, in the storefront currency. Applied to the rows this run reads. Applies in BOTH search mode and URL mode.

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

Fetch each item's product page for the description, merchant name, shipping cost, availability, GTIN/EAN, image gallery, category trail and return terms. Slower, and charged once per record. Leave off for a fast crawl: title, brand, price, currency, seller count and the product link are included either way.

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

The single cap on this run: stop after collecting this many records across all search terms and URLs. Set 0 for unlimited.

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

Safety bound on how many result pages to walk per search term or URL. Leave empty (0) for no page limit: the run then stops at Max items, not here. Does not impose a separate cap below Max items.

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

Leave the default for the cheapest run. The storefront is served over ordinary shared connections once the session is established; Residential is recommended for the most reliable results on large or frequent runs. If the run reports it could not read any results, try residential before anything else.

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

Paste a previous run ID or dataset ID to continue a large crawl without returning or charging for records already collected there. Use this after an interrupted or capped run. For recurring monitoring of the same search, use Incremental mode below instead.

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

Turn this on for daily or weekly recurring monitoring of the same search, for example a price watch. The first run returns everything matching as NEW. Later runs normally return only NEW, UPDATED and REAPPEARED records. Price moves and stock changes ARE reported as UPDATED: on a store they are the signal, not noise. Turn on Emit unchanged or Emit expired only when you also want those rows returned (and billed). State is kept separately per search, URL and filter setup; use State key to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from a previous run above.

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

Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently configured runs. Leave empty to let the actor derive a key automatically from the search terms, URLs and filters, so two different searches never mix state.

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

Off by default. Turn on to also return records that have not changed since the last run, marked UNCHANGED. This returns, and bills, extra rows you already have, so leave it off unless you specifically want a full snapshot every run.

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

Off by default. Turn on to also return records that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search: not when Max items capped it, not when Resume was used, and not when the run was refused. This returns, and bills, extra synthetic rows, so leave it off unless you need expiry tracking.

## `ignoreFieldsForChanges` (type: `array`):

Optional. Extra top-level field names to exclude from incremental change detection, on top of the built-in list. Use when a field moves every run without the product changing.

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

Optionally send results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize one under Apify, Settings, API and Integrations, then select it here. Notion gets a page per record; other connectors get a best-effort write or digest. Each connector receives a condensed summary per record, 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 record pages are created. Required to enable the Notion export; ignored by other connectors.

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

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

## Actor input object example

```json
{
  "mode": "search",
  "searchTerms": [
    "lego"
  ],
  "urls": [
    "https://www.fruugoaustralia.com/visine-eye-drops-red-eye-comfort-05-oz-15ml/p-307014223",
    "https://www.fruugoaustralia.com/visine-eye-drops-red-eye-comfort-05-oz-15ml/p-307014223-687617615",
    "https://www.fruugoaustralia.com/search?q=lego",
    "https://www.fruugoaustralia.com/search?q=lego&page=2"
  ],
  "country": "AU",
  "sort": "recommended",
  "fetchDetails": true,
  "maxItems": 20,
  "maxPages": 0,
  "proxy": {
    "useApifyProxy": true
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "ignoreFieldsForChanges": [],
  "maxNotifyListings": 50
}
```

# Actor output Schema

## `changes` (type: `string`):

No description

## `detail` (type: `string`):

No description

## `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 = {
    "mode": "search",
    "searchTerms": [
        "lego"
    ],
    "urls": [
        "https://www.fruugoaustralia.com/visine-eye-drops-red-eye-comfort-05-oz-15ml/p-307014223",
        "https://www.fruugoaustralia.com/visine-eye-drops-red-eye-comfort-05-oz-15ml/p-307014223-687617615",
        "https://www.fruugoaustralia.com/search?q=lego",
        "https://www.fruugoaustralia.com/search?q=lego&page=2"
    ],
    "country": "AU",
    "sort": "recommended",
    "fetchDetails": true,
    "maxItems": 20,
    "proxy": {
        "useApifyProxy": true
    },
    "incrementalMode": false,
    "emitUnchanged": false,
    "emitExpired": false,
    "ignoreFieldsForChanges": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("abotapi/fruugo-com-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 = {
    "mode": "search",
    "searchTerms": ["lego"],
    "urls": [
        "https://www.fruugoaustralia.com/visine-eye-drops-red-eye-comfort-05-oz-15ml/p-307014223",
        "https://www.fruugoaustralia.com/visine-eye-drops-red-eye-comfort-05-oz-15ml/p-307014223-687617615",
        "https://www.fruugoaustralia.com/search?q=lego",
        "https://www.fruugoaustralia.com/search?q=lego&page=2",
    ],
    "country": "AU",
    "sort": "recommended",
    "fetchDetails": True,
    "maxItems": 20,
    "proxy": { "useApifyProxy": True },
    "incrementalMode": False,
    "emitUnchanged": False,
    "emitExpired": False,
    "ignoreFieldsForChanges": [],
}

# Run the Actor and wait for it to finish
run = client.actor("abotapi/fruugo-com-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 '{
  "mode": "search",
  "searchTerms": [
    "lego"
  ],
  "urls": [
    "https://www.fruugoaustralia.com/visine-eye-drops-red-eye-comfort-05-oz-15ml/p-307014223",
    "https://www.fruugoaustralia.com/visine-eye-drops-red-eye-comfort-05-oz-15ml/p-307014223-687617615",
    "https://www.fruugoaustralia.com/search?q=lego",
    "https://www.fruugoaustralia.com/search?q=lego&page=2"
  ],
  "country": "AU",
  "sort": "recommended",
  "fetchDetails": true,
  "maxItems": 20,
  "proxy": {
    "useApifyProxy": true
  },
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "ignoreFieldsForChanges": []
}' |
apify call abotapi/fruugo-com-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abotapi/fruugo-com-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/H7Eg0ERASd9HMMUig/builds/2S5YmxeMpb60lqdhM/openapi.json
