# Csv Exorcist (`sindy-dill/csv-exorcist`) Actor

- **URL**: https://apify.com/sindy-dill/csv-exorcist.md
- **Developed by:** [Sindy Dill](https://apify.com/sindy-dill) (community)
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.03 / file cleaned

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?

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

## CSV Exorcist

**CSV Exorcist** turns a messy spreadsheet dump into a clean UTF-8 CSV and a short JSON report of what it fixed.

Upload a `.csv`, `.tsv`, `.txt`, or `.xlsx`, or paste CSV text. The Actor detects encoding and delimiter, trims cells, drops empty rows, drops exact duplicate rows, and writes two files you can download from the run storage.

It is a **deterministic file cleaner**, not an AI, not a scraper, and not a data-quality auditor. It will not invent columns, guess business meaning, or “fix” bad numbers.

### What it does

- Accepts a file upload, a public file URL, or pasted CSV text
- Reads CSV / TSV / TXT (encoding + delimiter sniffed) or XLSX (first sheet, or a named sheet)
- Normalizes blank / `Unnamed` headers
- Optionally strips cell whitespace
- Optionally drops rows that are empty in every cell
- Optionally drops exact duplicate rows
- Writes `CLEAN.csv` and `REPORT.json` to the run key-value store
- Pushes the same report to the default dataset

Runs with **limited permissions**. It only needs the file or text you give it.

### How to use it

1. Open the Actor and go to the **Input** tab.
2. Either **drop a file** (CSV / TSV / TXT / XLSX) or **paste CSV text**.
3. If you paste, press **Enter** between rows. Do not type the characters `\n`.
4. For Excel, set **Excel sheet name** only if you need a sheet other than the first.
5. Leave the three cleanup checkboxes on unless you want the raw grid preserved.
6. Click **Start**. When the run succeeds, open **Storage** → key-value store and download `CLEAN.csv`.

If both a file and pasted text are provided, the **file wins**.

#### Input fields

| Field | Required | Notes |
| --- | --- | --- |
| File | No\* | Use **Upload new file**, or a URL that downloads the file bytes. Drive/Dropbox *view* pages do not count. |
| Or paste CSV text | No\* | Real line breaks. Ignored if a file is set |
| Excel sheet name | No | XLSX only |
| Drop duplicate rows | No | Default on |
| Drop empty rows | No | Default on |
| Strip cell whitespace | No | Default on |

\* Provide **one** of file or paste.

### Output

**Key-value store**

- `CLEAN.csv` — cleaned table, UTF-8, comma-separated, header row
- `REPORT.json` — machine-readable summary

**Dataset** — one item, same shape as `REPORT.json`:

```json
{
  "ok": true,
  "source": "fileUrl",
  "filename": "export.csv",
  "kind": "csv",
  "detectedEncoding": "utf-8",
  "detectedDelimiter": ",",
  "sheetName": null,
  "rowsIn": 481,
  "rowsOut": 460,
  "columnsIn": ["Name", " Amount", "Date"],
  "columnsOut": ["Name", "Amount", "Date"],
  "emptyRowsDropped": 4,
  "duplicateRowsDropped": 17
}
```

Download the dataset as JSON, CSV, or Excel from the run page.

### Pricing

Priced **per cleaned file** on the pay-per-event plan (`file-cleaned`). See the **Pricing** tab for the live rate.

There is no extra charge for empty-row / duplicate-row work inside that file. Very large files cost the same event; they just use more run time. Current cap is **40 MB** per file.

### Limits and non-goals

- Max file size: **40 MB**
- One file (or one paste) per run
- XLSX: one sheet per run
- Does not parse `.xls` (legacy Excel 97–2003)
- Does not unsmerge cells, follow formulas, or keep Excel formatting
- Does not validate emails, tax IDs, or accounting mappings
- Thousands separators inside a field (e.g. `1,000`) stay as text unless you quoted them in the source file
- Password-protected workbooks are not supported

### FAQ

**Paste produced one giant row with `\n` in the cells.**\
The textarea received the two characters `\` and `n` instead of a line break. Paste again and press Enter between rows, or upload a file.

**File upload failed with 401/403.**\
Use a current build of this Actor. Uploads go through Apify storage and need the run token. Public `https://` URLs also work.

**Why did two rows that “look the same” both survive?**\
Duplicates must match on **every** column after trim. A trailing space that you turned off in **Strip cell whitespace**, or a hidden character, keeps both rows.

**Can I paste a Google Drive link?**\
A `/view` or “share” page is HTML, not the file. Preferred: **Upload new file**. If you must use Drive, the file must be shared with “anyone with the link,” and even then Google may show a confirm page the Actor cannot click through.

**Can I point this at Google Sheets?**\
A spreadsheet `/edit` URL is a webpage. Export CSV/XLSX and upload, or use a Sheets export URL (`.../export?format=csv`) on a sheet shared with anyone who has the link.

### Changelog

- **0.1** — File or paste in; encoding/delimiter sniff; empty-row and duplicate-row cleanup; `CLEAN.csv` + `REPORT.json`; limited permissions.

# Actor input Schema

## `fileUrl` (type: `string`):

CSV, TSV, TXT, or XLSX. You can upload here or paste a direct download URL.

## `csvText` (type: `string`):

Use this instead of a file. Ignored if a file is provided.

## `sheetName` (type: `string`):

Only for XLSX. Leave blank to use the first sheet.

## `dropDuplicateRows` (type: `boolean`):

Remove exact duplicate data rows after cleaning.

## `dropEmptyRows` (type: `boolean`):

Remove rows where every cell is empty.

## `stripWhitespace` (type: `boolean`):

Trim leading and trailing spaces inside each cell.

## Actor input object example

```json
{
  "dropDuplicateRows": true,
  "dropEmptyRows": true,
  "stripWhitespace": true
}
```

# Actor output Schema

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

// Run the Actor and wait for it to finish
const run = await client.actor("sindy-dill/csv-exorcist").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("sindy-dill/csv-exorcist").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 sindy-dill/csv-exorcist --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,sindy-dill/csv-exorcist"
        }
    }
}
```

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/JvQxsEIoZoboXHot4/builds/zF6Ei5uY3TBgGJxm2/openapi.json
