# Scraped Data Cleaner & Converter (No-Code CSV/JSON Tool) - PPE (`m3web/scraped-data-cleaner-ppe`) Actor

Clean and organize scraped .json or .csv data — no coding required. Remove duplicates, empty rows, unwanted columns, and sort by any field. Cleaned results are stored in Apify's Key-Value Store. Perfect for marketers, researchers, and no-code workflows.

- **URL**: https://apify.com/m3web/scraped-data-cleaner-ppe.md
- **Developed by:** [M3Web](https://apify.com/m3web) (community)
- **Categories:** Automation, Developer tools, Lead generation
- **Features:** Full permissions
- **Stats:** 7 total users, 0 monthly users, 100.0% runs succeeded, 2 bookmarks
- **User rating**: No ratings yet

## Pricing

$30.00 / 1,000 flat run fees

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

## 🧹 Scraped Data Cleaner & Converter (No-Code CSV/JSON Tool)

Clean and transform structured datasets from `.json` or `.csv` files — no coding required.

This Actor helps you prepare messy scraped data for analysis, import, or enrichment workflows. Whether you're working with leads, profiles, products, or survey results, it removes noise and gives you clean, structured rows you can actually use.

***

### ✅ Features

- Accepts both `.csv` and `.json` files (uploaded directly or linked from Apify Key-Value Store)
- Removes duplicate rows based on a field you choose (e.g. `email`, `sku`)
- Discards rows missing required data
- Choose whether **all** required fields must be filled or just **one**
- Optionally remove rows with no meaningful values
- Filter rows that match a specific field-value pair (e.g. `status = active`)
- Delete unwanted fields (columns in CSV / keys in JSON)
- Sort rows by one or more fields (text, number, date supported)
- Saves results in both `.csv` and `.json` formats — download links shown in log

***

### 🧾 How to Use

The Actor provides a clean no-code interface. Just upload a file and select any combination of cleaning options.

***

#### 1.1 📁 Uploaded Data File

Upload a `.csv` or `.json` file manually — or enter a full Apify Key-Value Store URL pointing to one.

When uploading directly, you'll see a window titled **“Upload file to key-value store”** with these options:

- ✅ **New temporary storage** *(recommended)* — creates short-lived storage with no additional cost
- 🗂️ **New permanent storage** — for keeping the file long-term
- 📁 **Existing storage** — reuse an existing Apify KV store

If you’re cleaning a one-off dataset, just use the default temporary option. It’s lightweight, instant, and cost-free.

***

#### 1.2 🧠 Deduplicate By Field

Specify a field name (e.g. `email`, `id`) to remove duplicate rows. Only the first occurrence of each unique value is kept.

#### 1.3 🧹 Remove Empty Rows

Enable to discard rows where all fields are blank, null, or empty strings. Works for both JSON and CSV rows.

***

#### 2.1.1 🔎 Must-Have Fields

List field names (e.g. `email`, `profile`, `company`) that should contain data. Rows missing those fields will be removed.

#### 2.1.2 🔎 Match All Required Fields

Enable for strict filtering: only rows with *all* listed fields filled will be kept.\
Disable to allow rows with *any one* field filled.

***

#### 2.2.1 🎯 Filter by Field

Specify a field name (e.g. `members`) to match against a specific value.

#### 2.2.2 🎯 Match Specific Value

Enter the exact value the field should contain (e.g. `pro`). Only rows with that exact match will be kept.

***

#### 3.1 🪓 Remove Columns (optional)

List column names you want deleted from every row (`status`, `id`, etc.). Applies to both CSV and JSON files.

***

#### 4.1 📌 Sort By Fields

Enter a list of field names to sort by, in order of priority (`status`, `createdAt`, `email`, etc.).

#### 4.2 🔄 Sort Descending

Enable to reverse the sort direction (Z–A, latest-to-earliest, etc.).

***

### 📁 Output

Cleaned results are stored in **Apify's Key-Value Store** and made available in **both `.csv` and `.json` formats**, regardless of original file type.

You'll see two download links directly in the Actor logs:

- 🟢 JSON format → `originalFileName-CLEANED.json`
- 🟠 CSV format → `originalFileName-CLEANED.csv`

Right-click and “Save link as…” to download the cleaned files.

No need to browse datasets, export manually, or convert formats — everything is ready to go.

***

### 🧠 What’s It Good For?

Let’s say you scraped a bunch of data — like contacts, products, survey answers, whatever. This tool helps clean it up and make it actually usable.

You can:

- Get rid of duplicate entries, like the same email showing up twice
- Filter out rows that are missing stuff you care about — like empty emails or profiles
- Keep only the ones with specific values (like people who have `status: active` or `members: pro`)
- Delete random columns you don’t need, like `internalNotes` or `debugInfo`
- Sort everything — by date, group, name, whatever you want
- Convert between `.json` and `.csv` so you can open the file wherever
- Basically, take any messy scraped file and make it clean, neat, and ready to use

It’s like having a smart assistant that tidies your data for you without writing a single line of code.

***

### 🛠 No Coding Required

You don’t need any JavaScript, parsing logic, or scripting knowledge. Just upload your file, tweak a few inputs, and go.

Ideal for:

- Marketers analyzing scraped leads
- Researchers organizing field data
- Journalists working with tabular records
- Data-driven workflows powered by no-code integrations

***

### 🔍 File Format Notes

- If your input is a `.json` array, the Actor auto-converts it to tabular `.csv` as well
- If your input is a `.csv`, the Actor also generates `.json` output for flexible reuse
- Result filenames follow this pattern:\
  `yourFileName-CLEANED.csv` and `yourFileName-CLEANED.json`

***

### 🧪 Sample Pre-Filled Input

To try it instantly, use the example CSV file provided in the interface or paste this Apify URL:\
`https://api.apify.com/v2/key-value-stores/9oIROyE5tcs83ZqP5/records/data-example.csv`

***

### 📊 Input vs Output Examples

#### 📄 Original CSV

| group | name    | email              | linkedin                          | status   | members |
|-------|---------|--------------------|-----------------------------------|----------|---------|
| 3     | Bob     | bob@example.com    |                                   | active   | basic   |
| 1     | Eve     | eve@example.com    |                                   | active   | pro     |
| 1     | Charlie |                    | https://linkedin.com/in/charlie   | inactive |         |
|       |         |                    |                                   |          |         |
| 2     | Dana    |                    |                                   | pending  | guest   |
| 1     | Eve     | eve@example.com    |                                   | active   | pro     |
| 1     | Alice   | alice@example.com  | https://linkedin.com/in/alice     | active   | pro     |

***

#### 1.2 🧠 Deduplicate By Field: `email`

Duplicate row for `eve@example.com` is removed.

| group | name    | email              | linkedin                          | status   | members |
|-------|---------|--------------------|-----------------------------------|----------|---------|
| 3     | Bob     | bob@example.com    |                                   | active   | basic   |
| 1     | Eve     | eve@example.com    |                                   | active   | pro     |
| 1     | Charlie |                    | https://linkedin.com/in/charlie   | inactive |         |
|       |         |                    |                                   |          |         |
| 2     | Dana    |                    |                                   | pending  | guest   |
| 1     | Alice   | alice@example.com  | https://linkedin.com/in/alice     | active   | pro     |

***

#### 1.3 🧹 Remove Empty Rows

Removes the row with no values (between Charlie and Dana).

| group | name    | email              | linkedin                          | status   | members |
|-------|---------|--------------------|-----------------------------------|----------|---------|
| 3     | Bob     | bob@example.com    |                                   | active   | basic   |
| 1     | Eve     | eve@example.com    |                                   | active   | pro     |
| 1     | Charlie |                    | https://linkedin.com/in/charlie   | inactive |         |
| 2     | Dana    |                    |                                   | pending  | guest   |
| 1     | Alice   | alice@example.com  | https://linkedin.com/in/alice     | active   | pro     |

***

#### 2.1.1 🔎 Required Fields: `email`, `linkedin`

2.1.2 🔎 Match All Required Fields: 🔘 OFF — keeps rows with **at least one** of the fields filled

| group | name    | email              | linkedin                          | status   | members |
|-------|---------|--------------------|-----------------------------------|----------|---------|
| 3     | Bob     | bob@example.com    |                                   | active   | basic   |
| 1     | Eve     | eve@example.com    |                                   | active   | pro     |
| 1     | Charlie |                    | https://linkedin.com/in/charlie   | inactive |         |
| 1     | Alice   | alice@example.com  | https://linkedin.com/in/alice     | active   | pro     |

***

#### 2.1.1 🔎 Required Fields: `email`, `linkedin`

2.1.2 🔎 Match All Required Fields: 🟢 ON — keeps only rows with **both** fields filled

| group | name  | email             | linkedin                      | status | members |
|-------|-------|-------------------|-------------------------------|--------|---------|
| 1     | Alice | alice@example.com | https://linkedin.com/in/alice | active | pro     |

***

#### 2.2.1 🎯 Filter by Field: `members`

2.2.2 🎯 Match Specific Value: `pro`

Keeps only rows where the `members` field is exactly `pro`.

| group | name    | email              | linkedin                          | status   | members |
|-------|---------|--------------------|-----------------------------------|----------|---------|
| 1     | Eve     | eve@example.com    |                                   | active   | pro     |
| 1     | Alice   | alice@example.com  | https://linkedin.com/in/alice     | active   | pro     |

***

#### 3.1 🪓 Remove Columns: `linkedin`, `status`

Removes those columns from all rows.

| group | name    | email              | members |
|-------|---------|--------------------|---------|
| 3     | Bob     | bob@example.com    | basic   |
| 1     | Eve     | eve@example.com    | pro     |
| 1     | Charlie |                    |         |
| 2     | Dana    |                    | guest   |
| 1     | Alice   | alice@example.com  | pro     |

***

#### 4.1 📌 Sort By Fields: `group`, then `name`

4.2 🔄 Sort Descending: 🔘 OFF — lowest group first, A–Z within group

| group | name    | email              | linkedin                          | status   | members |
|-------|---------|--------------------|-----------------------------------|----------|---------|
| 1     | Alice   | alice@example.com  | https://linkedin.com/in/alice     | active   | pro     |
| 1     | Charlie |                    | https://linkedin.com/in/charlie   | inactive |         |
| 1     | Eve     | eve@example.com    |                                   | active   | pro     |
| 2     | Dana    |                    |                                   | pending  | guest   |
| 3     | Bob     | bob@example.com    |                                   | active   | basic   |

***

#### 4.1 📌 Sort By Fields: `group`, then `name`

4.2 🔄 Sort Descending: 🟢 ON — highest group first, Z–A within group

| group | name    | email              | linkedin                          | status   | members |
|-------|---------|--------------------|-----------------------------------|----------|---------|
| 3     | Bob     | bob@example.com    |                                   | active   | basic   |
| 2     | Dana    |                    |                                   | pending  | guest   |
| 1     | Eve     | eve@example.com    |                                   | active   | pro     |
| 1     | Charlie |                    | https://linkedin.com/in/charlie   | inactive |         |
| 1     | Alice   | alice@example.com  | https://linkedin.com/in/alice     | active   | pro     |

***

### 💬 Feedback & Ideas

Want new filtering modes, regex support, or nested data handling?\
Have ideas to make it even simpler for non-coders? Just [send me a message](https://screentest.app/contact/) — I’d love to hear how you're using the tool.

# Actor input Schema

## `uploadedDataFile` (type: `string`):

Upload a CSV or JSON file, or paste a full Apify URL for a stored record. The file must contain structured rows of data with fields you want to clean or filter.

## `deduplicateBy` (type: `string`):

Enter the name of a field (e.g. 'email', 'product_id') to remove duplicate rows. Only the first row with each unique value will be kept.

## `removeEmpty` (type: `boolean`):

Removes rows that contain no meaningful data. Works for both CSV and JSON files.

## `requiredFields` (type: `array`):

Specify one or more field names (e.g. 'email', 'phone'). Rows missing required data in these fields will be removed.

## `requireAllFields` (type: `boolean`):

If checked, rows must contain data in ALL required fields. If unchecked, rows with data in ANY one required field will be kept.

## `requiredFieldKey` (type: `string`):

Keep only rows where this field matches a specific value. Enter the field name (e.g. 'member', 'status').

## `requiredFieldValue` (type: `string`):

Value to match for the field above (e.g. 'pro', 'active'). Only exact matches will be kept.

## `removeColumns` (type: `array`):

List of field names to remove from each row (e.g. 'email', 'internal_notes'). Applies to both CSV and JSON.

## `sortBy` (type: `array`):

Fields to sort by, in order of priority (e.g. 'status', 'created_at'). Applies to both CSV and JSON.

## `sortDescending` (type: `boolean`):

Enable to sort rows from Z–A or high-to-low for numeric/date values.

## Actor input object example

```json
{
  "uploadedDataFile": "https://api.apify.com/v2/key-value-stores/9oIROyE5tcs83ZqP5/records/data-example.csv",
  "deduplicateBy": "",
  "removeEmpty": true,
  "requireAllFields": false,
  "requiredFieldKey": "",
  "requiredFieldValue": "",
  "sortDescending": false
}
```

# 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 = {
    "uploadedDataFile": "https://api.apify.com/v2/key-value-stores/9oIROyE5tcs83ZqP5/records/data-example.csv"
};

// Run the Actor and wait for it to finish
const run = await client.actor("m3web/scraped-data-cleaner-ppe").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 = { "uploadedDataFile": "https://api.apify.com/v2/key-value-stores/9oIROyE5tcs83ZqP5/records/data-example.csv" }

# Run the Actor and wait for it to finish
run = client.actor("m3web/scraped-data-cleaner-ppe").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 '{
  "uploadedDataFile": "https://api.apify.com/v2/key-value-stores/9oIROyE5tcs83ZqP5/records/data-example.csv"
}' |
apify call m3web/scraped-data-cleaner-ppe --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,m3web/scraped-data-cleaner-ppe"
        }
    }
}
```

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/6vUbhqzmBOc3NWn8B/builds/q5I9dClQDrbG3olJn/openapi.json
