# CSV to Excel Converter - CSV to XLSX, by URL or Bulk (`eliai/csv-to-excel`) Actor

Convert CSV files to Excel spreadsheets by URL - proper quoted-field parsing, custom delimiters, headers detected, column widths set. Batch up to 25 files. Built for scripts, pipelines, and AI agents. $0.03 per file; failures are free.

- **URL**: https://apify.com/eliai/csv-to-excel.md
- **Developed by:** [Anthony Snider](https://apify.com/eliai) (community)
- **Categories:** Developer tools, Automation, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$30.00 / 1,000 converted files

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/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

## CSV to Excel Converter — CSV to XLSX Spreadsheet, by URL or Bulk

Turn a CSV file into a real Excel workbook without installing anything. Point this at
a `.csv` URL and get back a downloadable `.xlsx`: the header row becomes column names,
numbers arrive as numbers, and the things that usually get mangled — quoted fields,
commas inside quotes, leading zeros — arrive intact. Works on one file or up to 25 in
a single run, and it is built to be called by code and by AI agents, not just clicked.

**$0.03 per file converted.** No subscription, no seat fee, no minimum. You pay for
files you actually convert.

### What problem this solves

"Just open the CSV in Excel" is where the data goes wrong. Excel guesses: `01234`
becomes `1234`, a long order number becomes scientific notation, a European
semicolon file lands entirely in column A, and a product name containing a comma
splits itself across two cells. Doing it properly means writing a parser, or trusting
a random free upload site with data that may belong to a client.

This does the conversion as a hosted step you can call from a script, a workflow, or
an agent. The CSV is parsed to the actual RFC 4180 rules, the workbook comes back as
a URL you can download or hand straight to someone else, and nothing is guessed at.

### Who uses it

- **Data and ops engineers** turning a vendor's CSV export into the workbook finance opens.
- **Analysts** who need a clean sheet for a pivot table without fighting the import wizard.
- **AI agents** that produced or fetched a CSV and were asked for "a spreadsheet".
- **No-code / automation builders** (Make, n8n, and similar) that can call a URL but cannot
  write a binary `.xlsx`.
- **Anyone doing a bulk migration** — hand it 25 CSV URLs, get 25 workbooks.

### Quick start

```json
{
  "url": "https://graveyard.broke2builtai.com/assets/sample.csv"
}
```

That is the whole minimum input. Everything else is optional. (That URL is a live
10-row sample file, so you can run it as-is to see the output shape.)

#### All input options

| Field | Type | Required | What it does |
|---|---|---|---|
| `url` | string | **yes** | Direct URL to the `.csv` file |
| `urls` | string\[] | no | Extra CSV URLs — up to **25 total** per run |
| `delimiter` | string | no | Field separator (default `,`). Use `;` for European exports, `\t` for TSV |
| `hasHeader` | boolean | no | Default **true**. Off: columns become `column_1`, `column_2`, … |
| `sheetName` | string | no | Name of the sheet in the workbook (default `Sheet1`) |
| `maxRows` | number | no | Cap data rows (default **5000**) |
| `maxFileSizeMb` | number | no | Refuse files larger than this, uncharged (default **50**, max 200) |

### What you get back

This is the actual dataset item from a run against the sample URL above — not an
illustration:

```json
{
  "url": "https://graveyard.broke2builtai.com/assets/sample.csv",
  "finalUrl": "https://graveyard.broke2builtai.com/assets/sample.csv",
  "status": 200,
  "fileName": "sample.xlsx",
  "delimiter": ",",
  "sheetNames": ["Sheet1"],
  "sheets": [
    {
      "name": "Sheet1",
      "rowCount": 10,
      "columns": ["sku", "product", "category", "unit_price", "stock", "restock_date", "supplier"]
    }
  ],
  "downloadUrl": "https://api.apify.com/v2/key-value-stores/d84bac68-f53d-45dc-af32-181669e875c1/records/output-1.xlsx"
}
```

- `downloadUrl` — **the finished `.xlsx`**. Fetch it, or open it in a browser.
- `sheets[0].columns` — the header row that was written, in order.
- `sheets[0].rowCount` — data rows written (header excluded).
- `sheets[0].truncated` — present and `true` only if `maxRows` cut the file short.
- `fileName` — a suggested name, derived from the source URL (`sample.csv` → `sample.xlsx`).
- `finalUrl` — where the fetch actually landed, after redirects.

**One dataset item per input file.** A failed input returns `{ url, error }` instead of
throwing, so one bad link in a batch of 25 never kills the other 24 — and a file that
fails is never charged.

### How the parsing actually behaves

The CSV is read a character at a time, not split on commas, so these all survive:

| In the CSV | In the cell |
|---|---|
| `"Smith, John"` | `Smith, John` — the comma stays inside one cell |
| `"he said ""hi"""` | `he said "hi"` |
| a quoted field containing a line break | one cell, line break preserved |
| CRLF or LF line endings | both fine |
| a short or over-long row | padded with blanks, or a `column_N` added |
| a blank line | skipped |
| two columns both named `name` | `name` and `name_2` — neither is overwritten |

**Numbers stay numbers; identifiers stay text.** A value becomes a real Excel number
only if it is a plain integer or decimal that cannot lose information:

| Value | Result | Why |
|---|---|---|
| `4.50` | `4.5` (number) | trailing zeros are formatting, not content |
| `182` | `182` (number) | plain integer |
| `01234` | `01234` (text) | a leading zero is meaningful — zip codes stay intact |
| `+15551234` | text | a leading `+` is not arithmetic |
| `4111111111111111` | text | over 15 digits would lose precision as a float |
| `1e5` | text | never silently expanded to `100000` |
| empty | an empty cell | not the word "null" |

### Use it as an AI agent tool

This Actor is callable over **Apify MCP**, so an agent can produce a spreadsheet
mid-conversation without you writing an integration. The shape an agent needs:

- **Tool:** this Actor
- **Input:** `{ "url": "<csv url>" }`
- **Returns:** a `downloadUrl` pointing at a real `.xlsx` workbook

If your agent can be handed a link to a CSV, it can now hand back a spreadsheet.

### Pricing, plainly

**$0.03 per file converted** (pay-per-event: `file-converted`). A 25-file batch costs
$0.75. There is no monthly fee, and a run that converts nothing costs nothing.

### Honest limits

Worth knowing before you run it, so nothing surprises you:

- The file must be reachable at a **direct URL**. A Google Sheets *share* page is not a
  file URL — use the export link, or host the file somewhere fetchable.
- **One CSV in, one sheet out.** A run of 25 files produces 25 separate workbooks, not
  one workbook with 25 tabs.
- **Data only — no formulas, colours, fonts or merged cells.** Column widths are sized to
  the content; nothing else is styled.
- The delimiter is **not auto-detected** — it defaults to `,`, so pass `delimiter` for
  semicolon or tab files. (The `delimiter` used is echoed back in the output record.)
- Dates are written **as the text they were in the file**, not converted to Excel date
  values, because `03/04/2026` is genuinely ambiguous and guessing is how the wrong date
  ends up in a report.
- Files are read as **UTF-8** (a byte-order mark is stripped). A legacy Windows-1252
  export may show mangled accented characters.
- Up to **25 files per run** and, by default, 5000 rows (`maxRows`). Excel itself stops at
  1,048,575 data rows.
- Files over `maxFileSizeMb` (default 50 MB, max 200) are refused before download and never
  charged.

### FAQ

#### How do I convert CSV to Excel without installing anything?

Give this Actor the file's URL. It fetches the CSV, builds the workbook, and returns a
`downloadUrl` for the finished `.xlsx`. No local install, no import wizard.

#### Will it ruin my zip codes and long ID numbers like Excel does?

No — that is the main reason it exists. Values with leading zeros, a leading `+`, or more
than 15 digits are kept as text exactly as written. See the table above.

#### My CSV uses semicolons. Does that work?

Yes. Pass `{"delimiter": ";"}`. For tab-separated files pass `{"delimiter": "\t"}`.

#### What if my file has no header row?

Set `{"hasHeader": false}` and every row is treated as data, with columns named
`column_1`, `column_2`, and so on.

#### Does it handle commas and line breaks inside quoted fields?

Yes. The parser follows RFC 4180 — quoted fields, `""` for a literal quote, and commas or
newlines inside quotes are all preserved as one cell.

#### Can I convert multiple CSV files in one run?

Yes — up to 25 per run via `urls`. Each produces its own workbook and its own dataset item,
and a failure on one does not stop the rest.

#### What happens if the file is missing or is not really a CSV?

That input returns `{ url, error }` with a message naming the actual problem (HTTP status,
an HTML page instead of a file, an empty file). The run continues, the other files still
convert, and nothing is charged for the failure.

#### Where does my data go?

The Actor fetches the file, converts it, and writes both the record and the `.xlsx` to
**your** run's storage on your own Apify account. Delete the run and the output goes with it.

#### Can an AI agent call this?

Yes — it is exposed through Apify MCP as an agent tool. See "Use it as an AI agent tool".

### Who made this

[Broke to Built](https://broke2builtai.com) — a company of machines, building things
it gives away. This is one of them; the rest are free too.

### For AI agents

This Actor is built to be called by software, not just by people.

- **Mount it directly as an MCP tool** — no Store search, no ranking, just this one tool:
  `https://mcp.apify.com/?actors=eliai/csv-to-excel`
- **Or call it over HTTP** and get the results in the same request:
  `POST https://api.apify.com/v2/acts/eliai~csv-to-excel/run-sync-get-dataset-items`
- **Pay with x402, without an Apify account.** This Actor is whitelisted for agentic payments, so an agent holding USDC on Base can buy a prepaid token and spend it here. The minimum purchase is $1, the token balance is an absolute spending cap, and it expires 14 days after purchase.
- **Costs are predictable before you call.** Pricing is pay-per-event (see Pricing above), so an agent can budget a run in advance instead of discovering the bill afterwards.
- **Send only the field you mean.** If you pass the bulk field, it is used on its own; the single-value field is a fallback, never merged into your request. You are charged for the items you sent and nothing else.

# Actor input Schema

## `url` (type: `string`):

Direct URL to a .csv file. The first row is treated as the header unless you turn that off below.

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

Optional list of additional CSV file URLs to convert in one run (max 25 total).

## `delimiter` (type: `string`):

Field separator. Use ; for European exports, or \t for tab-separated files.

## `hasHeader` (type: `boolean`):

On: the first row becomes the column names. Off: columns are named column\_1, column\_2, … and every row is data.

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

Name for the single sheet in the produced workbook.

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

Cap the number of data rows written (header row excluded). Excel itself stops at 1,048,575 data rows.

## `maxFileSizeMb` (type: `integer`):

Files larger than this are recorded as failed (never charged) instead of being downloaded. Very large files can exhaust run memory, so raise this only with a higher memory setting.

## Actor input object example

```json
{
  "url": "https://graveyard.broke2builtai.com/assets/sample.csv",
  "urls": [],
  "delimiter": ",",
  "hasHeader": true,
  "sheetName": "Sheet1",
  "maxRows": 5000,
  "maxFileSizeMb": 50
}
```

# Actor output Schema

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

Every item this run produced, including a downloadUrl per workbook, as JSON.

## `resultsCsv` (type: `string`):

The same items as a spreadsheet-ready CSV.

## `workbooks` (type: `string`):

The key-value store holding every .xlsx workbook this run produced.

# 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 = {
    "url": "https://graveyard.broke2builtai.com/assets/sample.csv",
    "urls": [],
    "delimiter": ",",
    "sheetName": "Sheet1"
};

// Run the Actor and wait for it to finish
const run = await client.actor("eliai/csv-to-excel").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 = {
    "url": "https://graveyard.broke2builtai.com/assets/sample.csv",
    "urls": [],
    "delimiter": ",",
    "sheetName": "Sheet1",
}

# Run the Actor and wait for it to finish
run = client.actor("eliai/csv-to-excel").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 '{
  "url": "https://graveyard.broke2builtai.com/assets/sample.csv",
  "urls": [],
  "delimiter": ",",
  "sheetName": "Sheet1"
}' |
apify call eliai/csv-to-excel --silent --output-dataset

```

## MCP server setup

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

```

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/EE0RxkhpG03XNcnhl/builds/CWDaEb7fvhJ27TR0V/openapi.json
