# Freelancermap IT Freelance Projects Scraper (`scrapyx/freelancermap-projects-scraper`) Actor

Scrapes IT freelance/contract project listings from Freelancermap — a European freelance project board. Returns full job description, company, contract type, remote %, budget, duration and location for any search you paste in.

- **URL**: https://apify.com/scrapyx/freelancermap-projects-scraper.md
- **Developed by:** [Ibnu Adzim](https://apify.com/scrapyx) (community)
- **Categories:** Jobs, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.56 / 1,000 results

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

## Freelancermap IT Freelance Projects Scraper (Europe)

Scrapes IT freelance/contract project listings from
**[Freelancermap](https://www.freelancermap.com)** — a European freelance
project board.

Public data only. No login, no cookies, no browser. **No bot challenge of
any kind** — fully open `robots.txt`, no WAF observed on any surface
touched during recon.

### The one thing you need to know before using this

**Each search URL returns one page (~22 projects) — there is no working
pagination.** Freelancermap's own search page believes it has dozens of
pages, but every way of asking for page 2 (the exact link the site itself
generates, alternate parameter names, XHR-style headers) returned page 1's
content again — a real, verified constraint (see `CRAWLING_METHOD.md`), not
a missing feature. To get broader coverage, pass **multiple search URLs**
with different keywords, countries or categories rather than expecting one
URL to page through everything.

### What you get

Two record types share one dataset, told apart by `recordType`.

#### `PROJECT` — one row per listing

Rows are the upstream's own result objects, almost verbatim — `title`, a
**full HTML `description`** (not an excerpt — no detail page needed at
all), `company`/`poster` (contact info), `country`, `city`, `contractType`,
`projectContractType.remoteInPercent`, `budget`, `industry`,
`beginningText`/`durationText`, `created`/`updated`/`expires` timestamps,
and a computed `projectUrl`. Two internal ML-only fields (`embedding`, a
\~500-float recommendation vector, and `matching`, relevance-scoring
metadata) are dropped — everything else is passed through as-is.

#### `SEARCH_SUMMARY` — one row per search URL

How many projects came back, plus (informational only)
`upstreamBelievedTotalPages` — what the site's own pagination widget
claims, even though this actor cannot reach past page 1 (see above).

#### `ERROR` — one row per input that could not be processed

Every input maps to at least one row, so nothing disappears silently.

### Input

| Field | What it does |
| --- | --- |
| **Search URLs** | full `freelancermap.com/projects...` URLs, copied from the site — one fetch each |
| **Max concurrent requests** | absorbs latency variance — not the throttle |
| **Min interval between requests** | the actual speed control — 0.5s default |

#### Example

```json
{
  "searchUrls": [
    "https://www.freelancermap.com/projects?query=python",
    "https://www.freelancermap.com/projects?remoteInPercent=100",
    "https://www.freelancermap.com/projects/web-and-software-development"
  ]
}
```

### Notes on reliability

- **Query filters are genuinely applied server-side** — verified with
  `query=`, `countries=`, `remoteInPercent=`, and a gibberish query
  (honest zero results, not a silent fallback to the unfiltered baseline).
- **No WAF, no rate limit observed.** Residential proxy is still the cloud
  default, as elsewhere in this portfolio.

### Known limits

- **No pagination past page 1 of a given search URL** (see above) — this
  is the main thing to plan around when using this actor.
- **No detail-page enrichment offered or needed** — the search row already
  carries the full HTML description and every field the detail page would.

# Actor input Schema

## `searchUrls` (type: `array`):

Full freelancermap.com '/projects' search URLs — one fetch per entry, each with its own SEARCH\_SUMMARY row. Browse to any keyword/country/remote-% search on freelancermap.com and paste the resulting URL here (or a bare category path like /projects/web-and-software-development). Each URL returns that query's first page only (~22 projects) — freelancermap's own pagination (`pagenr=`) does not advance via plain HTTP, confirmed during recon; use different search URLs (keywords, countries, categories) for broader coverage rather than expecting one URL to page through everything.

## `maxConcurrency` (type: `integer`):

How many search URLs may be fetched at once. This absorbs latency variance; it is NOT the throttle — the crawl rate is set by 'Minimum interval between requests' below.

## `minRequestInterval` (type: `number`):

The actual speed control: the shortest gap between two requests to freelancermap, across all workers. No bot challenge of any kind was observed during recon — worth preserving with a sane default rate rather than an unthrottled burst.

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

Freelancermap ran no bot challenge at all during recon (open robots.txt, no WAF markers on any surface touched). Residential is still the cloud default — container egress is a different posture than a home connection.

## Actor input object example

```json
{
  "searchUrls": [
    "https://www.freelancermap.com/projects",
    "https://www.freelancermap.com/projects?query=python"
  ],
  "maxConcurrency": 5,
  "minRequestInterval": 0.5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `items` (type: `string`):

One row per scraped record. See the dataset's default view for field definitions.

# 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 = {
    "searchUrls": [
        "https://www.freelancermap.com/projects",
        "https://www.freelancermap.com/projects?query=python"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapyx/freelancermap-projects-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 = { "searchUrls": [
        "https://www.freelancermap.com/projects",
        "https://www.freelancermap.com/projects?query=python",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("scrapyx/freelancermap-projects-scraper").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 '{
  "searchUrls": [
    "https://www.freelancermap.com/projects",
    "https://www.freelancermap.com/projects?query=python"
  ]
}' |
apify call scrapyx/freelancermap-projects-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapyx/freelancermap-projects-scraper"
        }
    }
}
```

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/LILdR1wTJxW0x4GeV/builds/YvqtnzQuV6gv5malC/openapi.json
