# Incidecoder Ingredients Scraper (`automation-lab/incidecoder-cosmetic-products-ingredients`) Actor

Search public INCIDecoder products and export complete ingredient lists, functions, explanations, ratings, and formulation flags.

- **URL**: https://apify.com/automation-lab/incidecoder-cosmetic-products-ingredients.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.34 / 1,000 item extracteds

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

## INCIDecoder Ingredients Scraper

Export public **INCIDecoder ingredients** data as structured product records for formulation research. Search by product or brand, or supply exact product URLs. Each result includes product identity, brand, the ordered full ingredient list, normalized ingredient links, functions, explanations, aliases, disclosed irritancy and comedogenicity values, INCIDecoder ratings, and formulation flags.

### Who is it for?

- Cosmetic formulators comparing disclosed ingredient functions.
- Product and category teams researching competing formulations.
- Data analysts building normalized cosmetic ingredient datasets.
- Researchers tracking source-disclosed formulation flags.
- Catalog teams enriching known products with ordered ingredient details.

### Why use this Actor?

The source presents valuable details across an overview, a comparison table, and expanded ingredient cards. This Actor joins those surfaces into one stable nested record. It preserves source order and normalized links, avoids loading product images, deduplicates products found through multiple inputs, and charges only for useful product rows.

### What can you use it for?

- Compare formulations across products or brands.
- Build ingredient-function and product-flag datasets.
- Enrich an existing cosmetic catalog from known INCIDecoder URLs.
- Schedule repeat runs and compare datasets in your own database or automation.

### Extracted data

| Field | Meaning |
| --- | --- |
| `productName` | Product name shown by the source. |
| `brand` | Product brand when disclosed. |
| `productUrl` | Canonical INKEE Decoder product page. |
| `description` | Source product description. |
| `uploadedAt` | Source-disclosed upload date. |
| `imageUrl` | Public product image URL, without downloading the image. |
| `flags` | Formulation flags such as alcohol-free. |
| `ingredientCount` | Number of ingredients in source order. |
| `ingredientNames` | Spreadsheet-friendly ordered names. |
| `ingredients` | Full normalized ingredient objects. |
| `scrapedAt` | Extraction timestamp. |

### Getting started

1. Open the Actor input page.
2. Add a product or brand term under **Product or brand searches**.
3. Optionally add exact public product URLs.
4. Choose a product limit.
5. Start the run.
6. Open the **Product results** dataset view.
7. Export JSON, CSV, Excel, XML, or connect the dataset API.

### Input parameters

| Field | Description |
| --- | --- |
| `searchQueries` | Product, brand, or formulation terms to search. |
| `startUrls` | Exact public INCIDecoder product pages. |
| `maxItems` | Maximum product records (default 20, maximum 1,000). |
| `maxRequestRetries` | Bounded transient retries from 0 to 5. |

Provide at least one search query or product URL. Both modes deduplicate canonical product URLs and obey the same `maxItems` limit.

```json
{
  "searchQueries": ["CeraVe cleanser"],
  "maxItems": 3
}
```

### Output example

```json
{
  "productName": "Cleanser",
  "brand": "CeraVe",
  "productUrl": "https://inkeedecoder.com/products/cerave-cleanser",
  "flags": ["alcohol-free", "fragrance & essentialoil-free"],
  "ingredientCount": 22,
  "ingredientNames": ["Purified Water", "Cocamidopropyl Hydroxysultaine", "Glycerin"],
  "ingredients": [
    {
      "position": 1,
      "name": "Purified Water",
      "url": "https://inkeedecoder.com/ingredients/water",
      "functions": ["solvent"],
      "alsoCalled": ["Aqua", "Water"],
      "irritancy": null,
      "comedogenicity": null,
      "rating": null
    }
  ]
}
```

### Output details

One default-dataset row represents one product. The nested `ingredients` array preserves source order and contains `position`, `name`, normalized `url`, `functions`, `explanation`, `alsoCalled`, `irritancy`, `comedogenicity`, and `rating`. Product fields include `productName`, `brand`, `description`, `uploadedAt`, `imageUrl`, `flags`, `ingredientCount`, `ingredientNames`, `productUrl`, and `scrapedAt`.

Missing source disclosures are returned as `null` or empty arrays rather than inferred.

### How much does it cost to scrape INCIDecoder product ingredients?

Pay-per-event pricing has a $0.005 run start and a BRONZE product-result rate of $0.0039 per product. A run that returns 10 products emits 10 item events; a run that returns 100 emits 100 item events, in addition to the single start event. Higher usage tiers reduce the per-product rate. Failed, duplicate, and rejected pages are not charged as product results. Apify platform usage may also apply according to your plan.

### Example workflows

#### Brand formulation scan

Search a brand and cap the result count for a bounded snapshot. Store each dated dataset in your warehouse and compare ingredient arrays between snapshots.

#### Exact catalog enrichment

Map your known product URLs into `startUrls`. Join returned rows to your catalog by `productUrl`, then index `ingredientNames` for filtering.

#### Function research

Flatten each nested `ingredients` array downstream. Group by `functions`, keeping `productName`, `brand`, and ingredient `position` as context.

### Run with the API

#### cURL

```bash
curl -X POST "https://api.apify.com/v2/acts/automation-lab~incidecoder-cosmetic-products-ingredients/runs?token=$APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"startUrls":[{"url":"https://incidecoder.com/products/cerave-cleanser"}],"maxItems":1}'
```

After completion, fetch items from the run's default dataset.

#### JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/incidecoder-cosmetic-products-ingredients').call({
  searchQueries: ['CeraVe cleanser'],
  maxItems: 3,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient('YOUR_APIFY_TOKEN')
run = client.actor('automation-lab/incidecoder-cosmetic-products-ingredients').call(
    run_input={'searchQueries': ['CeraVe cleanser'], 'maxItems': 3}
)
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)
```

### MCP setup and prompts

#### Claude Code

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/incidecoder-cosmetic-products-ingredients"
```

#### Claude Desktop, Cursor, and VS Code

Add this MCP JSON configuration in the client's MCP settings:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/incidecoder-cosmetic-products-ingredients"
    }
  }
}
```

Example prompts:

- "Run the INCIDecoder Actor for CeraVe cleanser and summarize ingredient functions."
- "Extract these two INCIDecoder product URLs and compare formulation flags."
- "Return a table of ingredient name, position, function, and rating for this product."

### Integrations

Use the Apify MCP server to run this Actor from compatible AI clients. Scheduled Tasks, webhooks, Make, Zapier, Google Sheets, and database integrations can turn recurring runs into formulation-monitoring workflows.

### Reliability and limitations

- Only public INCIDecoder/INKEE Decoder product pages are supported.
- Search exports products visible in the public source search response; it does not claim exhaustive catalog coverage.
- Ratings, flags, functions, and explanations are source disclosures, not medical or safety advice.
- The source can rename fields, redirect its domain, rate-limit requests, or remove pages. Transient retries are bounded.
- The Actor does not bypass login, CAPTCHA, or private content.

### Legality and responsible use

Scrape only public data and comply with INCIDecoder's terms, applicable laws, and your intended use. Avoid excessive request volume. Product and ingredient descriptions belong to their respective owners.

### Troubleshooting

- **No records:** check that an exact URL points to `/products/...` or broaden the search term.
- **Page not found:** verify the product still exists publicly; redirects between INCIDecoder and INKEE Decoder are normalized automatically.
- **Temporary upstream error:** retry later or increase `maxRequestRetries` within the supported bound.

### Tips for reliable runs

- Prefer exact product URLs when reproducibility matters.
- Use specific search terms instead of a broad one-word query.
- Keep `maxItems` close to the volume you actually need.
- Schedule at a reasonable cadence and compare datasets downstream.
- Treat missing ratings as missing source disclosure, not a negative rating.

### FAQ

#### Does it return every ingredient?

Yes, it preserves the complete ingredient overview order shown on each successfully parsed product page.

#### Can I search and submit URLs together?

Yes. Results are deduplicated before extraction and capped by `maxItems`.

#### Does it assess ingredient safety?

No. It exports source-disclosed ratings and flags without producing medical, regulatory, or safety conclusions.

### Related Actors

Explore other [automation-lab Actors](https://apify.com/automation-lab) for product catalogs, public datasets, and research automation.

# Actor input Schema

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

Terms such as a brand, product, or formulation to find on INCIDecoder.

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

Public INCIDecoder product pages. Search results and non-product URLs are rejected.

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

Maximum number of product records to export across all searches and URLs.

## `maxRequestRetries` (type: `integer`):

Retries for transient network, rate-limit, and server errors.

## Actor input object example

```json
{
  "searchQueries": [
    "CeraVe cleanser"
  ],
  "startUrls": [
    {
      "url": "https://incidecoder.com/products/cerave-cleanser"
    }
  ],
  "maxItems": 20,
  "maxRequestRetries": 2
}
```

# Actor output Schema

## `overview` (type: `string`):

Default dataset containing one normalized record per successfully extracted product.

# 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": [
        "CeraVe cleanser"
    ],
    "startUrls": [
        {
            "url": "https://incidecoder.com/products/cerave-cleanser"
        }
    ],
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/incidecoder-cosmetic-products-ingredients").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": ["CeraVe cleanser"],
    "startUrls": [{ "url": "https://incidecoder.com/products/cerave-cleanser" }],
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/incidecoder-cosmetic-products-ingredients").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": [
    "CeraVe cleanser"
  ],
  "startUrls": [
    {
      "url": "https://incidecoder.com/products/cerave-cleanser"
    }
  ],
  "maxItems": 20
}' |
apify call automation-lab/incidecoder-cosmetic-products-ingredients --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/incidecoder-cosmetic-products-ingredients"
        }
    }
}

```

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/HKVhA2NbxobBAYSgY/builds/2FrjIEGPFmU6ZPWNx/openapi.json
