# CSV Combiner | 💾 Merge CSV Files with Custom Column Order (`amr-mando/csv-combiner`) Actor

Combine up to three CSV files into one. Columns are matched by header name, so data stays under the right column even when the files order their columns differently. You choose the output column order.

- **URL**: https://apify.com/amr-mando/csv-combiner.md
- **Developed by:** [Mando](https://apify.com/amr-mando) (community)
- **Categories:** Lead generation, E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.10 / actor start

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

## 🧩 CSV Combiner

Combine up to three CSV files into one. Columns are matched by their header name, so every value stays under the correct column even when the files list their columns in a different order. You decide the final column order.

***

### 📌 What it does

You have two or three CSV exports that hold the same kind of data but do not line up. One file has `Name, Email, Domain`, another has `Domain, Email, Name`, a third uses lowercase `email`. Pasting them together by hand mixes the data under the wrong headers.

This actor:

1. Reads each file by its **header names**, not by column position.
2. Matches columns across files (matching is **not case-sensitive**, so `Email`, `EMAIL`, and `email` are the same column).
3. Stacks every row into one combined CSV, each value placed under its correct header.
4. Writes the output in the **column order you choose**.

No row is removed. Every row from every file ends up in the output.

***

### 📥 Input

#### Input CSV Files

| Field | Required | Notes |
|-------|----------|-------|
| 📄 CSV 1 | Yes | The first file. |
| 📄 CSV 2 | No | Optional second file. |
| 📄 CSV 3 | No | Optional third file. |

You can run with 1, 2, or 3 files. Files do not need the same columns or the same column order.

#### 🧩 Output Column Order

A single dropdown controls the column order of the combined output:

- **📄 Use CSV 1 / 2 / 3 column order** - the output follows that file's header order. Any column that exists only in the other files is added at the end, with an `extra_` prefix on its name (for example `extra_Phone`). Nothing is dropped.
- **✍️ Custom order** - you type the exact column order you want in the text box below the dropdown.

#### ✍️ Custom Column Order

Used only when **Custom order** is selected. Write the column header names you want, **one per line** (press Enter between each, no commas):

```
Name
Email
Company
Domain
```

Rules for custom order:

- Order is exactly what you type, top to bottom.
- Matching is not case-sensitive. Typing `email` matches a `Email` column.
- The output keeps the original header casing from the file, not what you typed.
- Any combined column you do **not** list is **dropped** from the output.
- Any name you type that matches no column is skipped and reported in the log.

***

### 🔗 How columns are matched

Matching is by header name, lowercased and trimmed:

| CSV 1 header | CSV 2 header | Treated as |
|--------------|--------------|------------|
| `Email`      | `email`      | one column |
| `Domain `    | `domain`     | one column |
| `Job Title`  | `job title`  | one column |

When a file is missing a column that another file has, that cell is left blank for the rows from the file that lacks it.

***

### 📊 Log

The log opens with a short summary so you can see what happened before you download anything.

CSV 1 / 2 / 3 order:

```
📥 Loaded CSV files:
   CSV 1: 500 rows, 12 columns
   CSV 2: 320 rows, 10 columns
   CSV 3: 150 rows, 14 columns

🧩 Combined rows: 970

📊 Column analysis (across all files):
   Total unique columns: 20
   Columns with data:    15
   Empty columns:        5
   Empty: Fax, Middle Name, Region, Notes, Suffix

📋 Output column order: CSV 1
   12 columns from CSV 1, in its order
   + 8 extra column(s) from the other files, appended with the "extra_" prefix:
     extra_Phone, extra_LinkedIn, extra_Title, ...
```

Custom order:

```
📊 Column analysis (across all files):
   Total unique columns: 20
   Columns with data:    15
   Empty columns:        5

📋 Output column order: Custom (14 columns)
   Order: Domain, Name, Email, Company, ...
   ⚠️ 1 name(s) in your list matched no column and were skipped: emial
   ❌ 6 column(s) dropped (not in your order): Fax, Region, Notes, Phone, Suffix, Middle Name
      Of those, 1 held data: Phone
```

- **Total unique columns**: how many distinct columns exist once all files are combined.
- **Columns with data**: how many of those hold at least one non-empty value. The rest are blank in every row.
- **Dropped (custom order only)**: columns not in your list. The log also tells you how many of the dropped columns actually held data, so you know if you lost anything that mattered.

***

### 📤 Output

- **Dataset**: the combined rows, viewable as a table in the Apify console and available through the API.
- **Key-value store, key `OUTPUT`**: the combined CSV file, in the exact column order you chose, with original header casing. Download this for the clean file.

The output download link is shown on the run's Output tab.

***

### 📋 Example

**CSV 1** (`Name, Email, Company, Domain`)

| Name | Email | Company | Domain |
|------|-------|---------|--------|
| Alice | alice@acme.com | Acme | acme.com |

**CSV 2** (`Domain, Company, Email, Name, Phone`) - different order, extra `Phone`

| Domain | Company | Email | Name | Phone |
|--------|---------|-------|------|-------|
| globex.com | Globex | carol@globex.com | Carol | 555-0100 |

**CSV 3** (`email, name, title`) - lowercase headers, extra `title`, no company or domain

| email | name | title |
|-------|------|-------|
| eve@umbrella.com | Eve | CTO |

**Output column order: CSV 1**

| Name | Email | Company | Domain | extra\_Phone | extra\_title |
|------|-------|---------|--------|-------------|-------------|
| Alice | alice@acme.com | Acme | acme.com | | |
| Carol | carol@globex.com | Globex | globex.com | 555-0100 | |
| Eve | eve@umbrella.com | | | | CTO |

Carol's data came in as `Domain, Company, Email, Name, Phone` but still lands under the right headers. Eve's lowercase `email` matched `Email`, and her `title` was appended as `extra_title`.

***

### ⚠️ Notes

- Matching is case-insensitive and ignores leading and trailing spaces in headers.
- If two columns inside the **same** file share a header name, only one is kept for that file.
- No rows are removed. Duplicate rows across files are all kept.
- Empty CSVs, or files with no header row, are skipped with a warning. The run continues with the remaining files.

# Actor input Schema

## `csv1` (type: `string`):

Upload the first CSV file. This one is required. Columns are matched across files by their header name, so the column order inside this file does not need to match the others.

## `csv2` (type: `string`):

Upload the second CSV file. Optional. Its columns are matched to CSV 1 by header name. Any header it does not share with CSV 1 is still kept.

## `csv3` (type: `string`):

Upload the third CSV file. Optional. Its columns are matched to the other files by header name.

## `columnOrderSource` (type: `string`):

Choose which column order the combined CSV should follow. Pick one of the uploaded files to reuse its header order; columns that exist only in the other files are appended at the end with an "extra\_" prefix so nothing is lost. Pick "Custom order" to type your own order in the field below, which also drops any column you leave out.

## `customColumnOrder` (type: `string`):

Only used when "Custom order" is selected above. Write the column header names in the order you want them, one per line (press Enter between each, no commas). Matching is not case-sensitive. Any combined column you do not list here is dropped from the output, and the log reports exactly what was dropped and whether it held data.

## Actor input object example

```json
{
  "columnOrderSource": "csv1",
  "customColumnOrder": "Name\nEmail\nCompany\nDomain"
}
```

# Actor output Schema

## `csvOutput` (type: `string`):

No description

## `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 = {
    "customColumnOrder": `Name
Email
Company
Domain`
};

// Run the Actor and wait for it to finish
const run = await client.actor("amr-mando/csv-combiner").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 = { "customColumnOrder": """Name
Email
Company
Domain""" }

# Run the Actor and wait for it to finish
run = client.actor("amr-mando/csv-combiner").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "customColumnOrder": "Name\\nEmail\\nCompany\\nDomain"
}' |
apify call amr-mando/csv-combiner --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=amr-mando/csv-combiner",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/Jov0MCzq7ERzt4joH/builds/McdO6PMXcAWXP4pz8/openapi.json
