# French IT Contract Market - Day Rates & Hiring Companies (`koatiromeo/french-it-contract-market`) Actor

French IT contractor missions with structured day rates, plus what listings alone cannot give: median day rate per role and region, with p25, p75, sample size and the companies hiring. Deduplicated across Free-Work, Freelance-Informatique and Codeur. Incremental mode returns only new missions.

- **URL**: https://apify.com/koatiromeo/french-it-contract-market.md
- **Developed by:** [Koati Romeo](https://apify.com/koatiromeo) (community)
- **Categories:** Jobs, Lead generation
- **Stats:** 7 total users, 4 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $8.00 / 1,000 missions

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?

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

## French IT Contract Market — Day Rates & Hiring Companies

> **Unofficial tool.** Not affiliated with, endorsed by, or sponsored by Free-Work,
> Freelance-Informatique or Codeur.com.

French IT contractor missions, with the **day rate** attached — and the market
statistics you cannot get by reading the listings one by one.

Most job scrapers hand you rows. This one also hands you the answer to the
question those rows exist to support: **what is the going day rate for this role,
in this region, right now, and which companies are paying it.**

***

### What you get

**1. Missions** — one row per distinct mission, deduplicated across sources.
Title, company, day rate (min/max/period/currency), city, region, remote mode,
contract type, duration, skills, publication date, apply URL.

**2. A day-rate benchmark** — median, p25, p75, min, max, mean and sample size,
per role and per region, with the number of hiring companies and a sample of
their names. Written to the `rate-benchmarks` dataset and to the
`RATE_BENCHMARK` key-value record.

**3. A run report** — per-source counts and the real HTTP status code per host,
so a blocked source is never confused with an empty one.

***

### Sources

| Source | What it carries |
|---|---|
| **Free-Work** | The largest French IT contractor feed. Around 6,600 open contractor missions at the time of writing, with structured minimum and maximum day rates. |
| **Freelance-Informatique** | Missions from IT services firms and large accounts, often the same client reached through a different channel. |
| **Codeur.com** | SME project briefs with fixed budgets, plus the number of bids already placed on each. |

The same mission is frequently republished by several agencies. Rows that describe
one real mission are merged into a single row carrying `seenOnSources` and
`timesPublished` — so `timesPublished: 3` tells you a mission is being pushed hard
through three channels, instead of showing you three rows that look like three
opportunities.

***

### Example output

A mission:

```json
{
  "title": "Intégrateur de Solutions Progiciels Fraude H/F",
  "company": "Freelance.com",
  "company_url": "https://www.free-work.com/fr/tech-it/company/freelance-com-11",
  "rate_min": 400.0,
  "rate_max": 550.0,
  "rate_period": "day",
  "currency": "EUR",
  "rate_raw": "400.0-550.0 EUR/j",
  "city": "Schiltigheim",
  "region": "Grand Est",
  "country": "France",
  "remote": "partial",
  "contracts": ["freelance", "cdi"],
  "duration": "12 months",
  "experience_level": "expert",
  "skills": ["Monitoring", "NAS", "Scripting"],
  "published_at": "2026-08-15T08:11:19+00:00",
  "expires_at": "2026-08-20T21:59:59+00:00",
  "url": "https://www.free-work.com/fr/tech-it/job-mission/architecte-solutions/integrateur-de-solutions-progiciels-fraude-h-f",
  "source": "free-work",
  "uid": "53b8779fd8c2d949c758",
  "seenOnSources": ["free-work"],
  "timesPublished": 1,
  "recordType": "mission"
}
```

A benchmark row:

```json
{
  "role": "Developpeur Backend",
  "region": "France (toutes regions)",
  "currency": "EUR",
  "ratePeriod": "day",
  "sampleSize": 32,
  "median": 500.0,
  "p25": 450.0,
  "p75": 528.75,
  "min": 310.0,
  "max": 565.0,
  "mean": 478.44,
  "hiringCompanies": 12,
  "topCompanies": ["CELAD", "Craftman data", "Digistrat consulting", "Genwaves Group",
                   "ICSIS", "INFOTEL CONSEIL", "LeHibou", "OCTOGONE", "OMICRONE", "STHREE SAS"],
  "computedAt": "2026-08-15T12:16:48+00:00",
  "recordType": "rate_benchmark"
}
```

Roles are classified into 17 families (SRE/DevOps, Cloud/Infrastructure, Data
Engineer, Data Scientist/AI, BI/Analytics, Cybersecurity, Architect, Backend,
Frontend, Fullstack, Mobile, SAP/ERP, QA/Test, Network/System, Project Manager/PO,
Support, Database) and mapped to French administrative regions, plus `Remote`.

***

### How the numbers are kept honest

**No currency conversion, ever.** A rate always travels with its own currency, and
a benchmark group is one currency only. A wrong comparison is worse than a
missing one.

**No mixing of rate periods.** Day rates, annual salaries and fixed project
budgets are never averaged together.

**No benchmark below the sample threshold.** A median over two missions is an
anecdote. `benchmarkMinSample` defaults to 5, and groups below it are dropped
rather than published.

**Implausible rates are corrected, not propagated.** Some recruiters type an
annual salary into the day-rate field — measured at 6 occurrences out of roughly
1,900 rated missions. Six rows are enough to print a "maximum day rate of
€100,250". Those values are reclassified as annual, or dropped when they fit
nothing.

***

### Incremental mode

Set `onlyNewSinceLastRun` to `true` and the Actor remembers every mission it has
already returned, emitting only what is genuinely new. Built for scheduled
polling: you pay for new missions, not for the same ones every morning.

The benchmark is always computed on the **full** collection, never on the
incremental subset — otherwise the median would be calculated from a handful of
overnight postings.

The `rate-benchmarks` dataset is a named dataset, so it persists between runs and
accumulates. That is deliberate: with `computedAt` and `runId` on every row, a
daily schedule turns into a time series of the French IT rate market.

***

### Pricing

| Event | Price |
|---|---|
| `mission-scraped` | $0.008 per mission delivered |
| `rate-benchmark` | $0.10 per role/region benchmark |

Nothing is charged that is not delivered.

| Scenario | Cost |
|---|---|
| Test run — 300 missions, 16 benchmarks | **$4.00** |
| Full market snapshot — 6,600 contractor missions, ~94 benchmarks | **$62.20** |
| Daily incremental — ~150 new missions, benchmarks off | **$1.20 per day** |

Set `computeRateBenchmark` to `false` if you only want the raw missions.

***

### FAQ

**Do I need a proxy?**
No. These sources answer from datacenter IPs. The proxy input exists only as a
fallback.

**Why do some missions have no rate?**
Because the source does not publish one. Roughly a third of Free-Work missions
carry a structured day rate; the rest advertise the rate as negotiable. Nothing
is invented to fill the gap.

**Why is a role missing from the benchmark?**
Either fewer than `benchmarkMinSample` missions matched it, or the missions that
matched carried no rate. Lower `benchmarkMinSample` — but read the sample size
before trusting a small group.

**A source returned zero rows and the run still succeeded. Why?**
If at least one source works, the run completes and the failure is reported per
source, with the HTTP status per host in `RUN_REPORT`. If every source fails, the
run fails loudly. One source breaking should not cost you the rest of the data.

**A run returned nothing at all.**
Free-Work rate-limits by IP silently — it answers `200` with zero rows rather
than `429`. The Actor detects this and fails with an explicit message instead of
reporting an empty market. Raise `requestDelaySeconds`, or enable the proxy.

***

### Known limits

- **France only.** Missions outside France appear when a French source publishes
  them, but the coverage is not built for other countries.
- **Rate coverage is partial by nature** — around a third of missions publish a
  structured rate. The benchmark is computed on those.
- **Company names are the publisher**, which for agency listings is the agency,
  not the end client. The end client is usually described but not named — that is
  how this market advertises.
- **Role classification is keyword-based.** A mission with an unusual title may
  land in no role and be excluded from the benchmark; `missionsClassified` in the
  run report tells you how many were classified.

# Actor input Schema

## `sources` (type: `array`):

Which French platforms to collect from. Free-Work carries the largest volume of IT contractor missions with structured day rates.

## `maxMissions` (type: `integer`):

Total number of missions returned, across all sources. Missions are ordered most-recent-first, so the cap always keeps the freshest ones. Free-Work alone publishes around 6,600 contractor missions - raise this for a full market snapshot.

## `query` (type: `string`):

Free-text filter, for example 'kubernetes' or 'sap fi'. Every word must appear in the title, description or skills. Leave empty for the whole market.

## `sinceDays` (type: `integer`):

Drop anything older. Leave empty to keep every published mission.

## `contractorOnly` (type: `boolean`):

Filters out permanent roles server-side where the source supports it. Turn off to include permanent positions.

## `onlyNewSinceLastRun` (type: `boolean`):

Remembers every mission already returned and emits only what is genuinely new. Built for scheduled polling: you pay for new missions, not for the same ones every day.

## `computeRateBenchmark` (type: `boolean`):

Produces median, p25, p75, min, max and sample size per role and region, written to the 'rate-benchmarks' dataset and to the RATE\_BENCHMARK record. Always computed on the full collection, never on the incremental subset.

## `benchmarkMinSample` (type: `integer`):

No benchmark is emitted below this many missions. A median over 2 missions is an anecdote, not a market rate.

## `includeRaw` (type: `boolean`):

Adds the untouched source record to each row. Useful for debugging, heavy in storage.

## `requestDelaySeconds` (type: `number`):

Raise this if a source starts returning empty results - Free-Work throttles by IP silently, answering 200 with zero rows.

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

These sources work from datacenter IPs without a proxy. Enable one only if a source starts refusing or returning nothing.

## Actor input object example

```json
{
  "sources": [
    "free-work",
    "freelance-informatique"
  ],
  "maxMissions": 300,
  "query": "",
  "contractorOnly": true,
  "onlyNewSinceLastRun": false,
  "computeRateBenchmark": true,
  "benchmarkMinSample": 5,
  "includeRaw": false,
  "requestDelaySeconds": 0.4,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `missions` (type: `string`):

One row per distinct mission: title, company, day rate (min/max/period/currency), city, region, remote mode, contract type, duration, skills, publication date and URL. Listings republished across several platforms are merged into one row carrying seenOnSources.

## `rateBenchmark` (type: `string`):

Median, p25, p75, min, max, mean and sample size per role and region, with the number of hiring companies. Computed on the full collection, never on a partial subset, and never mixing rate periods or currencies.

## `runReport` (type: `string`):

Per-source counts, failures, and the real HTTP status codes per host - the fastest way to tell a blocked source from an empty one.

# 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 = {
    "sources": [
        "free-work",
        "freelance-informatique"
    ],
    "maxMissions": 300
};

// Run the Actor and wait for it to finish
const run = await client.actor("koatiromeo/french-it-contract-market").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 = {
    "sources": [
        "free-work",
        "freelance-informatique",
    ],
    "maxMissions": 300,
}

# Run the Actor and wait for it to finish
run = client.actor("koatiromeo/french-it-contract-market").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 '{
  "sources": [
    "free-work",
    "freelance-informatique"
  ],
  "maxMissions": 300
}' |
apify call koatiromeo/french-it-contract-market --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,koatiromeo/french-it-contract-market"
        }
    }
}

```

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/px2PuNUY8jvGq1jes/builds/HeLGClGgTip90h0gG/openapi.json
