# Bulk ChatGPT & Claude: Classify, Extract & Translate Datasets (`tidydata/ai-dataset-enricher`) Actor

Run AI on every row of a dataset, CSV, Excel or Google Sheet: classify, sentiment analysis, extract fields, summarize, translate or your own prompt. Answers are added as new columns. No API key needed, or bring your own OpenAI, Claude, Gemini or OpenRouter key.

- **URL**: https://apify.com/tidydata/ai-dataset-enricher.md
- **Developed by:** [tidydata](https://apify.com/tidydata) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 row processed by the built-in ai (fast)s

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

## Bulk ChatGPT & Claude for datasets: classify, extract, summarize and translate every row

Run an AI model on **every row** of your data and get the answers back as **new columns**. Feed it the results of any Apify scraper, a CSV, an Excel file or a Google Sheet, pick a task, and download a clean table.

- **No API key needed.** The built-in AI (OpenAI's open GPT-OSS models: 20B for speed, 120B for harder work) is included in the price per row.
- **Or bring your own key** for OpenAI (ChatGPT), Anthropic (Claude), Google Gemini, OpenRouter (350+ models), Groq, DeepSeek or Mistral, and pay a much lower price per row.
- **Built for scraper output.** Pick a dataset from your Apify storage, or chain it as an **integration** after any Actor (Google Maps, reviews, jobs, products, comments…).
- **Failed rows are free.** If the AI can't process a row, you get the row back with an `ai_error` column and you are not charged for it.

### What can it do?

| Task | You give | New columns |
|---|---|---|
| **Classify** | Your categories, e.g. `Complaint, Question, Praise, Spam` | `ai_label` (or `ai_labels`), `ai_confidence` |
| **Sentiment analysis** | Nothing else | `ai_sentiment` (positive / negative / neutral / mixed), `ai_score` (-1 to 1), `ai_reason` |
| **Extract fields** | The columns you want, e.g. `price: the price as a number` | One column per field (`null` when not found) |
| **Summarize** | Length in words | `ai_summary` |
| **Translate** | Target language | `<field>_<code>`, e.g. `title_es`, `description_es` |
| **Custom prompt** | Your instruction, with `{field}` placeholders if you want | `ai_answer`, or your own columns |

### Typical uses

- **Lead qualification:** classify companies from Google Maps or a website crawl as B2B / B2C, by industry, or by fit for your offer.
- **Review and comment analysis:** sentiment and topics for app reviews, product reviews, YouTube or social comments.
- **Data cleaning:** extract price, currency, brand, city or email from messy text fields into proper columns.
- **Content work:** summarize articles, translate product catalogs, write a personalised first line for each lead (`Write a one-line opener for {name} at {company}`).
- **Tagging at scale:** route support tickets, label job posts by seniority, flag spam.

### How to use it

1. Choose **what the AI should do** (task).
2. Add your data: pick **Apify datasets**, paste **file links** (CSV, Excel, JSON, public Google Sheets) or **paste texts**.
3. Optional: limit which fields are sent with **Only send these fields** (by default all text fields are sent; IDs, URLs and image links are skipped).
4. Run. Download the result as CSV, Excel or JSON, or send it on with another integration.

#### Run it after a scraper (integration)

In the scraper's **Integrations** tab, add this Actor and set **Apify datasets** to `{{resource.defaultDatasetId}}`. Every time the scraper finishes, its rows are enriched automatically.

#### Example input (classify Google Maps places)

```json
{
  "task": "classify",
  "labels": ["Restaurant", "Cafe", "Bar", "Bakery", "Other"],
  "datasetIds": ["YOUR_DATASET_ID"],
  "inputFields": ["title", "categoryName", "description"]
}
```

#### Example output

```json
{
  "text": "The delivery was two days late and the box was crushed, but support refunded me quickly.",
  "ai_sentiment": "mixed",
  "ai_score": -0.2,
  "ai_reason": "Late, damaged delivery but quick refund from support"
}
```

### Pricing

Pay per row that the AI processed successfully. Failed rows and input problems are never charged.

| Mode | Price per row |
|---|---|
| Built-in AI, fast (default) | **$0.001** (1,000 rows = $1) |
| Built-in AI, smart | $0.004 |
| Your own API key | $0.0002 (you pay your AI provider directly) |

Higher Apify plans get store discounts automatically. Set **Maximum cost per run** in the run options and the Actor stops before going over it.

Users on Apify's free plan can try the built-in AI on the first 20 rows of each run; add your own API key to process more.

### Tips

- **Very large jobs:** the built-in AI has a shared daily capacity. If it is reached, the run stops cleanly, unprocessed rows are not charged, and you can continue tomorrow or add your own API key to process any volume.
- **Duplicates are processed once.** Identical rows reuse the same answer.
- **Long rows** are cut to 4,000 characters by default (change *Max characters sent per row*).
- **Rate limits with your own key:** lower *Parallel requests* if your provider returns 429 errors; the Actor retries automatically.
- **Privacy:** rows are sent only to the AI provider you use for the run; nothing is stored by this Actor beyond your run's dataset.

### FAQ

**Do I need an OpenAI or Anthropic account?** No. Leave *Your API key* empty and the built-in AI is used.

**Which model is used?** Built-in fast mode uses GPT-OSS 20B and smart mode GPT-OSS 120B, OpenAI's open-weight models. With your own key you can name any model your provider offers.

**Can it read Excel and Google Sheets?** Yes: public links to `.xlsx`, `.csv`, `.json` files and Google Sheets shared as "Anyone with the link can view".

**What if the AI is unsure?** Classify returns `ai_confidence` (0 to 1) so you can filter low-confidence rows. Extract returns `null` instead of guessing.

Questions or a feature request? Open an issue on this Actor's page: we answer quickly.

# Actor input Schema

## `task` (type: `string`):

Pick a ready-made task or write your own prompt. The answer is added to each row as new columns.

## `instruction` (type: `string`):

For 'Custom prompt': what to do with each row, e.g. 'Is this company B2B or B2C?'. You can insert row values with {field}, e.g. 'Write a one-line cold email opener for {name}, who works at {company}.' For 'Classify' it is optional extra guidance.

## `labels` (type: `array`):

The categories the AI can choose from, one per item, e.g. Complaint, Question, Praise, Spam.

## `multiLabel` (type: `boolean`):

Classify only: return every category that applies instead of exactly one.

## `outputFields` (type: `array`):

One column per item as  name: what it should contain, e.g.  price: the product price as a number  ·  email: contact email  ·  is_b2b: true or false. The AI fills them (null when unknown).

## `targetLanguage` (type: `string`):

Language to translate into, e.g. English, Spanish, German. New columns get the language code, e.g. title_es.

## `summaryWords` (type: `integer`):

Summarize only: maximum words per summary.

## `translateSummary` (type: `boolean`):

Summarize only: by default each summary is in the language of the row.

## `datasetIds` (type: `array`):

Pick one or more datasets from your storages (e.g. results of a scraper). When this Actor runs as an integration after another Actor, use {{resource.defaultDatasetId}}.

## `fileUrls` (type: `array`):

Public links to .csv, .xlsx or .json files, or Google Sheets shared as 'Anyone with the link can view'.

## `texts` (type: `array`):

One text per item (reviews, comments, titles, descriptions…). Each becomes a row with a 'text' column.

## `inputFields` (type: `array`):

Optional. By default every text field of the row is sent (IDs, URLs and image links are skipped). Nested fields: author.name.

## `maxRows` (type: `integer`):

Optional limit. 0 or empty = all rows.

## `quality` (type: `string`):

Used when you don't add your own API key. No account or key needed: the price per row includes the AI.

## `apiProvider` (type: `string`):

Only used if you add your own API key below. With your own key you pay the AI provider directly and this Actor charges a much lower price per row.

## `apiKey` (type: `string`):

Optional. Your key for the provider above. It is stored encrypted and only used for this run.

## `model` (type: `string`):

Optional, e.g. gpt-5-mini, claude-haiku-5-5, gemini-2.5-flash, openai/gpt-oss-120b. Empty = a fast, cheap default for that provider.

## `outputPrefix` (type: `string`):

New columns are named like ai_label, ai_sentiment, ai_summary. Use an empty prefix for plain names.

## `keepOriginalFields` (type: `boolean`):

Output each original row plus the new AI columns. Untick to output only the AI columns.

## `maxCharsPerRow` (type: `integer`):

Long rows are cut to this length before being sent to the AI.

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

How many rows are processed at the same time. Lower it if your own API key hits rate limits.

## Actor input object example

```json
{
  "task": "sentiment",
  "multiLabel": false,
  "targetLanguage": "English",
  "summaryWords": 40,
  "translateSummary": false,
  "quality": "fast",
  "apiProvider": "openai",
  "outputPrefix": "ai_",
  "keepOriginalFields": true,
  "maxCharsPerRow": 4000,
  "concurrency": 8
}
```

# Actor output Schema

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

One row per result.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("tidydata/ai-dataset-enricher").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("tidydata/ai-dataset-enricher").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 '{}' |
apify call tidydata/ai-dataset-enricher --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tidydata/ai-dataset-enricher"
        }
    }
}
```

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/9QEVE10henAPKR3WB/builds/Rgkhgq6LjIGVLRPGL/openapi.json
