Malt Fr Scraper
Pricing
from $2.80 / 1,000 results
Malt Fr Scraper
Scrape freelance profiles from the Malt directory (malt.fr, malt.de, malt.es): name, headline, skills, day rate, location, rating, missions and recommendations. Search by skill, role or city. Backed by Malt's internal JSON search API.
Pricing
from $2.80 / 1,000 results
Rating
0.0
(0)
Developer
Ahmed Jasarevic
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Malt Freelancer Scraper
Scrape freelancer profiles from the Malt directory — malt.fr (France), malt.de (Germany) and malt.es (Spain). Get names, headlines, skills, day rates (TJM), location, ratings, missions, availability and profile URLs as clean, structured JSON.
Malt is protected by Cloudflare. This Actor talks to Malt's internal JSON search API (/search/api/profiles) using a Chrome-impersonating HTTP client routed through Apify Proxy's Unblocker group, so it returns data without a browser, DOM scraping or a third-party anti-bot service.
What it does
- Searches Malt's freelancer directory by keyword/role per selected country domain.
- Expands each keyword into query variants (
react→react freelance,react senior,react remote, …). Malt returns a fixed top-24 per exact query but a different 24 for each query string, so variants are largely disjoint — this is the main coverage lever (a single keyword easily yields 100+ unique profiles). - Also repeats each query to surface more of Malt's randomised per-query sample.
- Returns a flat row per freelancer, ready for CSV/Excel/Sheets export.
- Optionally enriches each profile with spoken languages, experience level, category/sub-category, description and availability — fetched in parallel.
- Deduplicates across keywords, query variants, repetitions and domains.
- Handles the platform
abortingevent so a stopped run ends quickly.
Input
| Field | Type | Description |
|---|---|---|
searchTerms | string[] | Required. Skills/roles to search (e.g. react, data scientist). |
locations | string[] | Optional location filter. Note: Malt's guest API currently ignores it and returns the same randomised sample. |
domains | string[] | Which sites to search: fr, de, es. Default fr. |
maxItems | integer | Max freelancers to save. Default 100. |
expandWithVariants | boolean | Expand each keyword into query variants (the main coverage lever). Default true. |
variantModifiers | string[] | Words appended to each term when expanding (e.g. senior, remote). Default: freelance, senior, expert, junior, lead, remote, consultant, indépendant. |
maxRepetitions | integer | Times to repeat each query to surface more of Malt's randomised sample (1–30). Default 10. Stops early once a query stops yielding new profiles. |
scrapeProfileDetails | boolean | Fetch each profile page in parallel for languages/experience/category/description. Billed as an extra profile-detail event. |
maxConcurrency | integer | Parallel search requests (1–8). Default 5. |
category, speciality, businessSector, experienceLevel, language | string | Optional filters passed to Malt's search. |
minDayRate, maxDayRate | integer | Optional day-rate range. |
proxy | object | Apify Proxy config. Defaults to the UNBLOCKER group. |
Coverage note. Malt's public guest API ignores paging, sorting and
location, and returns a fixed top-24 per exact query. The reliable way to collect many freelancers is to vary the query string: the Actor appendsvariantModifiersto each term (and can also repeat a query), which yields largely-disjoint result sets. DisableexpandWithVariantsif you want a strict exact-match search.
Example input
{"searchTerms": ["react", "data scientist"],"domains": ["fr"],"maxItems": 100,"expandWithVariants": true,"scrapeProfileDetails": false}
Output
Each item in the default dataset contains (profile-detail fields are only present when scrapeProfileDetails is enabled):
name, firstName, lastName, headline, skills, certifiedSkills, dayRate, dayRateCurrency, dayRateFormatted, dayRateVisibility, city, country, countryCode, locationType, rating, missionsCount, recommendationsCount, appraisalsWithRatesCount, badges, availabilityStatus, availabilityFrequency, languages, experienceLevel, category, subCategory, description, photoUrl, profileUrl, sourceDomain, searchTerm, searchLocation, scrapedAt.
Example output item
{"name": "Sébastien D.","headline": "Développeur Front-End Senior | React | TypeScript","skills": ["React.js", "Next.js", "TypeScript", "JavaScript"],"dayRate": 600,"dayRateCurrency": "EUR","city": "Rennes","country": "France","countryCode": "FR","rating": 5,"missionsCount": 4,"profileUrl": "https://www.malt.fr/profile/sebastienD","sourceDomain": "fr","searchTerm": "react","scrapedAt": "2026-10-12T13:30:00.000Z"}
How it works
- Builds the query list: each keyword, plus (by default) one query per variant modifier (e.g.
react senior), per domain. - Calls
GET https://www.malt.{fr|de|es}/search/api/profiles?q=<query>withimpit(Chrome TLS impersonation) through Apify Proxy'sUNBLOCKERgroup, retrying transient403/429/5xxand Cloudflare HTML challenges. - Repeats each query up to
maxRepetitionstimes (sequentially, since concurrent draws return the same sample), stopping after three consecutive draws add nothing new. - Normalizes the JSON response and pushes one item per freelancer as soon as it is found.
- Optionally fetches each public profile page and decodes the embedded Nuxt payload for extra fields.
Pricing
This Actor supports pay-per-event (PPE) monetization. Enable it and define the events in Apify Console → your Actor → Publication → Monetization:
| Event | Charged when | Suggested price |
|---|---|---|
apify-actor-start | Once per run (synthetic, automatic). | $0.00005 |
apify-default-dataset-item | Per freelancer written to the dataset (synthetic, automatic). | $0.001 |
profile-detail | Per profile page fetched when scrapeProfileDetails is enabled (custom). | $0.002 |
So the base per-freelancer price stays cheap, and the heavy full-details mode costs extra per profile. If pay-per-event is not enabled, the Actor.charge calls are a safe no-op. The Actor respects the run's maximum cost and stops charging/working once the limit is reached.
Proxy & cost
Cloudflare blocks datacenter IPs and unsupported regions from Malt, so the Actor defaults to the Apify Proxy Unblocker group — the piece that makes requests succeed. Unblocker is billed in units (10 units per successful request) and/or residential transfer; see Apify Proxy pricing. You can point the proxy input at a different Apify Proxy group or turn it off if you have another working route.
Only publicly available freelancer data is collected. Use it responsibly and in line with Malt's terms of service.