# Ingredients Online Scraper — Bulk Ingredients & Stock (`crawloop/ingredientsonline-scraper`) Actor

Scrape Ingredients Online bulk wholesale ingredients by keyword, product, category, or factory. Export SKUs, pack sizes, public prices, US warehouse inventory, and seller factories for sourcing and monitoring.

- **URL**: https://apify.com/crawloop/ingredientsonline-scraper.md
- **Developed by:** [Andrej Kiva](https://apify.com/crawloop) (community)
- **Categories:** E-commerce, Lead generation, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.79 / 1,000 product listings

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/platform/actors/running/actors-in-store#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

## Ingredients Online Scraper — Bulk Ingredients & Stock

> **Ingredients Online scraper** for B2B **bulk wholesale ingredients** — SKUs, pack sizes, public price ranges, US warehouse inventory, and seller factories as clean JSON.

| Actor | Role |
| :--- | :--- |
| **Ingredients Online Scraper** ◄── you are here | US bulk / nutraceutical ingredient catalog + stock |
| [Europages Scraper](https://apify.com/crawloop/europages-scraper) | Broad EU B2B company directory |
| [WLW Scraper](https://apify.com/crawloop/wlw-scraper) | DACH B2B suppliers (Wer liefert was) |

> **Disclaimer:** Unofficial Actor for publicly accessible Ingredients Online pages and APIs. **Ingredients Online**, **GWI**, and related names are trademarks of their respective owners. Not affiliated with, sponsored by, or endorsed by Ingredients Online / Global Warehouse Industries. Provided for informational and research purposes only. You are responsible for complying with applicable laws and Ingredients Online terms of use.

Need an **Ingredients Online API alternative** for procurement or competitive monitoring? This Actor scrapes the public Magento GraphQL catalog so you can export **wholesale food additives**, **nutraceutical ingredients**, **vitamins**, **botanicals**, and **factory** profiles with **stock status** and optional **warehouse qty / lead times**. Run from the Apify Console or automate with **Python**, **Node.js**, **cURL**, or **MCP** / AI assistants.

***

### When to use this Actor

- **Keyword search** for bulk ingredients (coconut oil, whey protein, citric acid, botanical extracts, …)
- **Catalog crawls** of the full wholesale listing grid (`/products/` and category pages)
- **Product enrichment** — pack types, variants, public GraphQL price ranges, QC document labels
- **US warehouse inventory** — qty, location, lead time, restock date via the public warehouse API
- **Factory / seller intelligence** — manufacturer id + nested SKU lists
- **Full factory directory** with `scrapeAllFactories` (~1.4k sitemap URLs)

### When not to use this Actor

- **VIP / logged-in-only pricing** or **QC PDF downloads** — many files and some prices stay gated (`price.priceGated` is set when GraphQL withholds numbers)
- **Checkout, sample-request, or RFQ form automation**
- **Generic EU B2B company lookup** — chain to Europages / WLW instead
- **Recipe / grocery / barcode databases** — wrong ICP for this Actor

***

### Key Features

- Magento GraphQL search & catalog pagination (typically **no headless browser**)
- Product detail enrichment with pack variants and public price ranges
- Public warehouse inventory enrichment (US locations)
- Factory pages + sitemap factory dump
- Filters: in-stock only, max pages / page size
- Fast HTTP via `curl_cffi` Chrome TLS impersonation; proxy optional

***

### Use Cases

| Use case | What you get | Why it helps |
| :--- | :--- | :--- |
| **Ingredient sourcing** | Matching SKUs + factory names | Build R\&D / procurement shortlists |
| **Price & stock monitoring** | `price` + `inventory` on enriched products | Track US warehouse availability over time |
| **Factory coverage** | Factory profile + product list | Map who sells what on the marketplace |
| **Catalog export** | Paginated listing rows (~3k active SKUs) | Local research DB for nutraceuticals / food ingredients |
| **Doc discovery** | SDS / Spec / Allergen labels | See which SKUs publish QC documents publicly |

***

### Input Parameters

| Parameter | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `searchQueries` | Array | — | Keyword searches |
| `startUrls` | Array | — | Product, factory, or catalog URLs |
| `scrapeAllFactories` | Boolean | `false` | Crawl factories from sitemap |
| `maxItems` | Integer | `50` | Max dataset rows |
| `maxPages` | Integer | `1` | Max pages per search / catalog / factory product list |
| `pageSize` | Integer | `20` | GraphQL page size (1–50) |
| `enrichProducts` | Boolean | `false` | Listing → full product + inventory |
| `includeInventory` | Boolean | `true` | Warehouse qty / lead times on products |
| `includeDocuments` | Boolean | `true` | Detect QC document labels on PDPs |
| `includeFactoryProducts` | Boolean | `true` | Nested products on factory records |
| `inStockOnly` | Boolean | `false` | Filter search/catalog to IN\_STOCK |
| `requestDelaySecs` | Number | `0.4` | Delay between requests |
| `proxyConfiguration` | Object | off | Optional Apify Proxy |

#### Input Example — search + product + factory

```json
{
  "searchQueries": ["coconut oil"],
  "startUrls": [
    "https://www.ingredientsonline.com/food-additives/coconut-oil-cg/",
    "https://www.ingredientsonline.com/factory/cargill/"
  ],
  "maxItems": 25,
  "maxPages": 1,
  "enrichProducts": true,
  "includeInventory": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

#### Input Example — factory sitemap dump

```json
{
  "scrapeAllFactories": true,
  "includeFactoryProducts": true,
  "maxItems": 100,
  "maxPages": 1
}
```

***

### Output

| Field | Type | Description |
| :--- | :--- | :--- |
| `recordType` | String | `listing` | `product` | `factory` | `error` |
| `url` | String | Canonical page URL |
| `productId` / `sku` / `name` / `slug` | — | Product identifiers |
| `stockStatus` | String | `IN_STOCK` / `OUT_OF_STOCK` |
| `factoryName` / `factorySlug` / `manufacturerId` | — | Seller / factory refs |
| `price` | Object | Public price range + `priceGated` flag |
| `packOptions` / `variants` | Array | Package types and child SKUs |
| `inventory` | Array | Warehouse locations, qty, lead time |
| `documentLabels` | Array | SDS, Spec Sheet, Allergen, … |
| `categories` | Array | Category tree |
| `products` | Array | Nested SKUs on factory records |
| `searchQuery` / `page` / `resultsCount` | — | Search context |
| `scrapedAt` | String | ISO-8601 UTC |

#### Example product row

```json
{
  "source": "ingredientsonline",
  "recordType": "product",
  "url": "https://www.ingredientsonline.com/food-additives/coconut-oil-cg/",
  "productId": "33491",
  "sku": "110079-CARGILL-99999",
  "name": "Coconut Oil (CG 76) by Cargill",
  "stockStatus": "OUT_OF_STOCK",
  "factoryName": "Cargill",
  "price": {
    "currency": "USD",
    "lowest": 200,
    "highest": 200,
    "hasTier": true,
    "priceGated": false
  },
  "packOptions": [
    {
      "code": "pack_type",
      "label": "Package Type",
      "values": [{ "label": "420lb Drum", "valueIndex": 1583 }]
    }
  ],
  "inventory": [
    {
      "sku": "110079-313-11162-99999",
      "locations": [
        {
          "locationName": "GWI-Chino",
          "qty": "0",
          "leadTime": 0,
          "leadTimeUom": "days"
        }
      ]
    }
  ],
  "documentLabels": ["SDS", "Allergen Statement", "Spec Sheet", "Flow Chart", "Sample COA"],
  "scrapedAt": "2026-08-08T12:00:00+00:00"
}
```

***

### Integration examples

#### Node.js

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('crawloop/ingredientsonline-scraper').call({
  searchQueries: ['whey protein'],
  maxItems: 20,
  enrichProducts: true,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient(token="YOUR_TOKEN")
run = client.actor("crawloop/ingredientsonline-scraper").call(
    run_input={
        "searchQueries": ["whey protein"],
        "maxItems": 20,
        "enrichProducts": True,
    }
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["name"], item.get("sku"), item.get("stockStatus"))
```

#### cURL

```bash
curl "https://api.apify.com/v2/acts/crawloop~ingredientsonline-scraper/runs?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"searchQueries":["citric acid"],"maxItems":10,"enrichProducts":true}'
```

***

### MCP and AI assistants

Use this Actor from AI tools via [Apify MCP](https://docs.apify.com/platform/integrations/mcp).
Connect your Apify account, then call this Actor by its Store ID / name.

Example prompts:

- "Run Ingredients Online Scraper for coconut oil and return the top 20 SKUs with price and stock as JSON"
- "Scrape factory cargill on Ingredients Online and list nested products with warehouse inventory"
- "Crawl Ingredients Online factories via sitemap, then run Europages Scraper for the same company names in the EU directory"

***

### Suite next step

After Ingredients Online SKUs and US warehouse stock, map the same suppliers in broader EU industrial directories with [Europages Scraper](https://apify.com/crawloop/europages-scraper) or DACH coverage via [WLW Scraper](https://apify.com/crawloop/wlw-scraper).

***

### FAQ

**Is this an Ingredients Online API?**\
There is no official public product API for most buyers. This Actor is an **Ingredients Online scraper / API alternative** over public GraphQL, HTML, sitemap, and warehouse endpoints.

**Does this Actor log in?**\
No. Guest-accessible data only.

**Why does the site say “Log in to see pricing” while some rows still have prices?**\
The storefront UI hides prices for guests, but Magento GraphQL often still returns `price_range` / `custom_range`. When values are withheld, `price.priceGated` is true and amounts may be zero.

**Can I download SDS / Spec PDFs?**\
Document **labels** are detected on product pages. File downloads usually need a registered account and are out of scope.

**How large is the catalog?**\
On the order of ~3k active products and ~1.4k factory pages (varies over time).

**Do I need residential proxy?**\
Usually not for GraphQL catalog/search. Enable Apify Proxy only if you hit blocks.

# Actor input Schema

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

Ingredients Online keyword searches (e.g. coconut oil, whey protein, citric acid). Each query is paginated via Magento GraphQL.

## `startUrls` (type: `array`):

Ingredients Online URLs to scrape: product pages (/{category}/{slug}/), factory pages (/factory/{slug}/), or catalog pages (/products/, /value-added-ingredients/).

## `scrapeAllFactories` (type: `boolean`):

Discover factory URLs from the public sitemap (~1.4k) and scrape each profile up to maxItems.

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

Stop after this many dataset items (listings, products, factories).

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

Maximum pages per search query, category catalog, or factory product list (default page size 20).

## `pageSize` (type: `integer`):

GraphQL page size for product listings (1–50).

## `enrichProducts` (type: `boolean`):

When scraping search or catalog listings, also fetch full product detail (variants, pack types, document labels, warehouse inventory).

## `includeInventory` (type: `boolean`):

On product enrichment / product URLs, call the public warehouse API for qty, location, lead time, and restock date.

## `includeDocuments` (type: `boolean`):

On product pages, detect public QC document labels (SDS, Spec Sheet, Allergen, etc.). File downloads usually require login.

## `includeFactoryProducts` (type: `boolean`):

When scraping factory pages, attach a nested products array (paginated via manufacturer filter).

## `inStockOnly` (type: `boolean`):

When searching or crawling catalogs, filter to IN\_STOCK products only.

## `requestDelaySecs` (type: `number`):

Pause between HTTP / GraphQL requests on the same session.

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

Optional Apify Proxy. GraphQL usually works without proxy; enable residential if you see blocks.

## Actor input object example

```json
{
  "searchQueries": [
    "coconut oil"
  ],
  "startUrls": [
    "https://www.ingredientsonline.com/food-additives/coconut-oil-cg/",
    "https://www.ingredientsonline.com/factory/cargill/"
  ],
  "scrapeAllFactories": false,
  "maxItems": 50,
  "maxPages": 1,
  "pageSize": 20,
  "enrichProducts": false,
  "includeInventory": true,
  "includeDocuments": true,
  "includeFactoryProducts": true,
  "inStockOnly": false,
  "requestDelaySecs": 0.4,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Default dataset items.

# 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 = {
    "searchQueries": [
        "coconut oil"
    ],
    "startUrls": [
        "https://www.ingredientsonline.com/food-additives/coconut-oil-cg/",
        "https://www.ingredientsonline.com/factory/cargill/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawloop/ingredientsonline-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 = {
    "searchQueries": ["coconut oil"],
    "startUrls": [
        "https://www.ingredientsonline.com/food-additives/coconut-oil-cg/",
        "https://www.ingredientsonline.com/factory/cargill/",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("crawloop/ingredientsonline-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 '{
  "searchQueries": [
    "coconut oil"
  ],
  "startUrls": [
    "https://www.ingredientsonline.com/food-additives/coconut-oil-cg/",
    "https://www.ingredientsonline.com/factory/cargill/"
  ]
}' |
apify call crawloop/ingredientsonline-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,crawloop/ingredientsonline-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/AmGc9lRQLmuLt6OOu/builds/718VKr5gyZqIjoCPu/openapi.json
