# Malt Scraper — French Freelancer Marketplace Profiles (`studio-amba/malt-scraper`) Actor

Scrape freelancer profiles from Malt.fr, France's largest freelance marketplace. Search by skill or role and city to get name, headline, skills, day rate (TJM), location, rating, and mission count. No login required.

- **URL**: https://apify.com/studio-amba/malt-scraper.md
- **Developed by:** [Studio Amba](https://apify.com/studio-amba) (community)
- **Categories:** Business, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 result scrapeds

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 a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use 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

## Malt Scraper

Extract freelancer profiles from Malt.fr — search by skill or role and city, and get name, headline, skills, day rate (TJM), rating, and mission history for each freelancer.

### Why use this actor?

Malt is France's largest freelance marketplace, with over a million registered freelancers across tech, design, marketing, and consulting. Agencies sourcing subcontractors, recruiters building freelancer talent pools, and market researchers benchmarking day rates (TJM) by skill and city all need this data without manually browsing hundreds of profiles. This actor turns a skill + city search into a clean, structured dataset in seconds.

### How to scrape Malt.fr data

Malt.fr runs behind a Cloudflare managed challenge on every page, including its search endpoint, and its own `robots.txt` explicitly disallows the query-string search path (`/s?q=...`). Scraping the search results directly is both technically blocked and against the site's own crawl rules.

Instead, this actor uses Malt's public SEO landing pages — the directory structure at `/a/freelance/{category}/{role}/{city}` (for example `/a/freelance/tech/developpeur-backend/paris`). These pages are explicitly allowed by `robots.txt`, are indexed by Google, and are server-rendered with real freelancer cards baked into the page: name, headline, skills, day rate, rating, and mission count, all embedded in the page's Nuxt.js data payload.

To reach these pages reliably, the actor routes requests through Bright Data's Web Unlocker, which handles Malt's Cloudflare challenge automatically. It then parses the embedded JSON payload (Malt's Nuxt "devalue" format, a flat array of cross-referenced values) to pull out every freelancer card on the page, merging the "available now" and "experienced" freelancer lists and removing duplicates.

Give it a skill (in French — "développeur", "ux designer", "community manager") and a French city, and it maps your query to the matching Malt directory page, plus a handful of neighboring city pages if you ask for more results than a single page holds.

### Input

| Field | Type | Required | Description |
|-------|------|----------|--------------|
| `searchQuery` | String | No | Skill or role keyword, in French (default: `développeur`). Examples: `ux designer`, `data scientist`, `chef de projet`. |
| `location` | String | No | French city (default: `Paris`). Examples: `Lyon`, `Marseille`, `Bordeaux`, `Lille`, `Toulouse`, `Nantes`, `Rennes`, `Strasbourg`, `Montpellier`. |
| `maxResults` | Integer | No | Maximum freelancer profiles to return (default: 20, max: 200). |
| `brightDataApiKey` | String | No | Your own Bright Data Web Unlocker API key. Leave empty to use the built-in unlocking service. |
| `proxyConfiguration` | Object | No | Legacy field, kept for backwards compatibility. Ignored — fetching goes through Bright Data. |

### Output

Each result contains:

| Field | Type | Example |
|-------|------|---------|
| `id` | String | `"62fdff4b6b1f8c2dc07631a9"` |
| `name` | String | `"Abdoulaye Dabo"` |
| `headline` | String | `"Développeur Back-End \| PHP \| Symfony \| ERP"` |
| `skills` | Array | `["PHP", "Symfony", "MySQL", "Docker", ...]` |
| `dayRate` | Number | `500` |
| `currency` | String | `"EUR"` |
| `location` | String | `"Enghien-les-Bains"` |
| `locationType` | String | `"EVERYWHERE"` |
| `rating` | Number | `5` |
| `reviewCount` | Number | `12` |
| `missionsCount` | Number | `3` |
| `availability` | String | `"AVAILABLE_AND_VERIFIED"` |
| `photoUrl` | String | Freelancer profile photo URL |
| `url` | String | Full Malt profile URL |
| `role` | String | `"Développeur Backend"` |
| `scrapedAt` | String | `"2026-07-14T10:00:00.000Z"` |

### Example output

```json
{
    "id": "62fdff4b6b1f8c2dc07631a9",
    "name": "Abdoulaye Dabo",
    "headline": "Développeur Back-End | PHP | Symfony | ERP",
    "skills": ["Développement Back-End", "PHP", "Symfony", "MySQL", "Docker"],
    "dayRate": 500,
    "currency": "EUR",
    "location": "Enghien-les-Bains",
    "locationType": "EVERYWHERE",
    "rating": 5,
    "reviewCount": 0,
    "missionsCount": 3,
    "availability": "AVAILABLE_AND_VERIFIED",
    "photoUrl": "https://dam.malt.com/e5b7bbb4-a7a5-411d-bf78-b5b3c9be3c35",
    "url": "https://www.malt.fr/profile/abdoulayedabo",
    "role": "Développeur Backend",
    "scrapedAt": "2026-07-14T10:00:00.000Z"
}
````

### Cost estimate

This actor uses approximately **1-2 compute units per 100 results** (one Bright Data Web Unlocker request typically returns 12-24 unique freelancer profiles). At standard Apify pricing, that's roughly **$0.50-$1.00 per 1,000 profiles**.

### Limitations

- Malt does not expose true keyword search results outside its Cloudflare-protected app — this actor uses the site's own public SEO directory pages, which cover the most common skills and cities but not every possible search combination.
- Each directory page carries roughly 12-24 unique freelancer profiles; large `maxResults` values are filled by combining nearby city pages for the same role.
- Skill keywords are matched against a curated catalog of ~35 common Malt role categories (developer, designer, marketing, consulting, etc.). Unrecognized keywords fall back to the closest general role.
- Data is scraped from the public website and may change without notice.
- Respect Malt's terms of service and use responsibly.

### Frequently asked questions

**Does this require a Malt account or login?**
No. The actor scrapes Malt's public directory pages, which don't require authentication.

**Can I search by any skill?**
The actor matches your keyword against a curated catalog of ~35 common Malt role categories spanning tech, design, marketing, communication, project management, and consulting. Very niche or highly specific keywords fall back to the closest general role — check the `role` field in the output to confirm what was matched.

**Why isn't a specific freelancer showing up?**
This actor surfaces the freelancers Malt itself features on its public directory pages for a given skill and city, not a full database dump of every registered freelancer. Malt's own search behind login shows a wider pool.

**How fresh is the data?**
Every run scrapes live pages at request time, so day rates, availability, and mission counts reflect Malt's current data.

### Need this data on a schedule, or a custom version?

We run this scraper as a managed service for businesses: scheduled runs,
deduplication, delta detection, and delivery to your inbox, Google Sheets,
or API — maintenance included. We can also build a custom version with your
exact fields and filters, or combine multiple sources into one feed.

See [studioamba.dev/services](https://studioamba.dev/services/) or email
<hello@studioamba.dev> for a free data sample.
We maintain 300+ European web scrapers and answer within one business day.

# Actor input Schema

## `searchQuery` (type: `string`):

Search for freelancers by skill or role, in French. Example: 'développeur', 'ux designer', 'community manager', 'data scientist'.

## `location` (type: `string`):

French city to search in. Example: 'Paris', 'Lyon', 'Marseille', 'Bordeaux', 'Lille', 'Toulouse', 'Nantes', 'Rennes', 'Strasbourg', 'Montpellier'. Unrecognized cities fall back to Paris.

## `maxResults` (type: `integer`):

Maximum number of freelancer profiles to return. Each Malt landing page carries roughly 12-24 unique profiles; the actor pages through several role/city combinations to reach this total.

## `brightDataApiKey` (type: `string`):

Optional: your own Bright Data API key for the Web Unlocker zone. Leave empty to use the built-in unlocking service.

## `proxyConfiguration` (type: `object`):

Legacy field, kept for backwards compatibility. Fetching goes through the built-in Bright Data Web Unlocker (required to pass Malt's Cloudflare challenge), so this is ignored.

## Actor input object example

```json
{
  "searchQuery": "développeur",
  "location": "Paris",
  "maxResults": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# 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 = {
    "searchQuery": "développeur",
    "location": "Paris",
    "maxResults": 20,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("studio-amba/malt-scraper").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 = {
    "searchQuery": "développeur",
    "location": "Paris",
    "maxResults": 20,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("studio-amba/malt-scraper").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 '{
  "searchQuery": "développeur",
  "location": "Paris",
  "maxResults": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call studio-amba/malt-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=studio-amba/malt-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Malt Scraper — French Freelancer Marketplace Profiles",
        "description": "Scrape freelancer profiles from Malt.fr, France's largest freelance marketplace. Search by skill or role and city to get name, headline, skills, day rate (TJM), location, rating, and mission count. No login required.",
        "version": "0.1",
        "x-build-id": "X8UjXOGejCMtBtBAt"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/studio-amba~malt-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-studio-amba-malt-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/studio-amba~malt-scraper/runs": {
            "post": {
                "operationId": "runs-sync-studio-amba-malt-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/studio-amba~malt-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-studio-amba-malt-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "searchQuery": {
                        "title": "Skill / Role Keyword",
                        "type": "string",
                        "description": "Search for freelancers by skill or role, in French. Example: 'développeur', 'ux designer', 'community manager', 'data scientist'."
                    },
                    "location": {
                        "title": "City",
                        "type": "string",
                        "description": "French city to search in. Example: 'Paris', 'Lyon', 'Marseille', 'Bordeaux', 'Lille', 'Toulouse', 'Nantes', 'Rennes', 'Strasbourg', 'Montpellier'. Unrecognized cities fall back to Paris."
                    },
                    "maxResults": {
                        "title": "Max Results",
                        "minimum": 1,
                        "maximum": 200,
                        "type": "integer",
                        "description": "Maximum number of freelancer profiles to return. Each Malt landing page carries roughly 12-24 unique profiles; the actor pages through several role/city combinations to reach this total.",
                        "default": 20
                    },
                    "brightDataApiKey": {
                        "title": "Bright Data API Key (optional)",
                        "type": "string",
                        "description": "Optional: your own Bright Data API key for the Web Unlocker zone. Leave empty to use the built-in unlocking service."
                    },
                    "proxyConfiguration": {
                        "title": "Proxy Configuration",
                        "type": "object",
                        "description": "Legacy field, kept for backwards compatibility. Fetching goes through the built-in Bright Data Web Unlocker (required to pass Malt's Cloudflare challenge), so this is ignored."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
