# Freelancer.com Scraper - Projects, Budgets & Client Data (`dami_studio/freelancer-com-scraper`) Actor

On Freelancer.com the client names a budget and freelancers bid against it, and the site publishes the bid count and the average bid. Every row carries those next to the budget in its own currency, marked fixed or hourly, plus skills, client country and rating. $0.45 per 1,000.

- **URL**: https://apify.com/dami\_studio/freelancer-com-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.45 / 1,000 project returneds

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

## Freelancer.com Scraper - projects, budgets, bids and client data

On **Freelancer.com** the client names a budget and freelancers bid against it, and the site keeps
that tally in public: `bid_count`, how many have already bid, and `bid_avg`, what they are asking on
average. This actor keeps both next to the budget, so you can go after work nobody has quoted on yet
(set maximum bids to 5) or read the going rate for a skill.

Each row also carries title, full description, budget, required skills, the client's country and
star rating, and the listing upgrade flags. Export as JSON, CSV or Excel. There's nothing to log
into and no API key to supply.

It reads Freelancer's own public project API, plus the endpoint the site's project pages call for
the employer panel. No browser is involved, which is what keeps runs fast and cheap.

### What you get, per project

| Field | Example |
|---|---|
| `projectId`, `title`, `description`, `projectUrl` | `40634950`, "DNS Configuration and Testing for SMTP Providers" |
| `projectType`, `budgetType` | `fixed` / `fixed_price`, or `hourly` / `hourly_rate` |
| `budgetMin`, `budgetMax`, `budgetCurrency` | `10`, `15`, `USD` |
| `budgetMinUsd`, `budgetMaxUsd` | converted with the exchange rate Freelancer returns for that project |
| `bidCount`, `averageBid`, `averageBidUsd` | `41`, `18.22`, `18.22` |
| `hourlyCommitmentHours`, `hourlyCommitmentInterval`, `hourlyDuration` | `40`, `week`, `unspecified` |
| `skills`, `skillIds`, `categories` | `["System Admin","Linux","DNS"]` |
| `clientCountry`, `clientCountryCode`, `clientCity` | `United States`, `US`, `Kansas City` |
| `clientRating`, `clientReviewCount`, `clientMemberSince` | `5`, `1`, `2026-08-07T00:00:00.000Z` |
| `clientPaymentVerified`, `clientEmailVerified`, `clientPhoneVerified`, `clientProfileComplete`, `clientDepositMade` | `true` / `false` |
| `isSealed`, `isFeatured`, `isUrgent`, `isNda`, `isFulltime`, `isPremium`, `isRecruiter`, `isLocal`, `bidsHidden` | booleans |
| `postedAt`, `updatedAt`, `bidPeriodDays`, `bidsCloseAt`, `status`, `language` | ISO 8601 timestamps |
| `projectCountry`, `projectCity` | only set on the ~4% of projects that are local/on-site |

### Budgets: three different numbers, never blended

Freelancer projects carry money in more than one place, and mixing them produces nonsense. This
actor keeps them apart and labels every row:

- **`budgetMin` / `budgetMax`** is what the *client asked for*. On a `fixed` project that is a
  total. On an `hourly` project those exact same fields are an **hourly rate**. `USD 15-25` means
  $15-25 per hour, not $15-25 for the job. `budgetType` says which, on every single row.
- **`averageBid`** is what *freelancers are actually bidding*, which is frequently nowhere near the
  budget. In the sample row above the budget is $10-15 and the average bid is $18.22.
- Everything is also given in USD (`budgetMinUsd`, `budgetMaxUsd`, `averageBidUsd`) so you can sort
  a mixed-currency export. Roughly 46% of live projects are in USD and 37% in INR, so this matters.

None of this is estimated or inferred. Every budget is the number the client typed in.

### Measured coverage (994 live projects, sampled 8 Aug 2026)

These are the numbers one real run produced:

| Field | Present |
|---|---|
| `description` | 100% |
| `skills` | 100% |
| `budgetMin` | 100% |
| `budgetMax` | 98.3% (the rest are open-ended, e.g. "$100000+") |
| `bidCount` / `averageBid` | 96.6% (the rest have no bids yet) |
| `clientCountry` | 100% |
| `clientCity` | 95.8% |
| **`clientRating` above zero** | **31.7%** |
| `clientPaymentVerified` = true | 47.5% |

That client-rating number is the one to pay attention to. **About two thirds of Freelancer clients
have never been reviewed**, so their rating is a genuine `0` with `clientReviewCount: 0`. Read the
review count before you read the rating; a 0-star client is usually a new one, not a bad one.

Project type split: 76% fixed price, 24% hourly. Listing upgrades are rare: featured 0.5%,
sealed 0.5%, urgent 0.6%, NDA 0.4%.

### Billing

**$0.45 per 1,000 projects**, plus a $0.001 start fee per run. It's a flat rate, the same number on
the free plan as on any paid one.

One charge per project row you actually receive. Projects dropped by `clientCountries`,
`minBudgetUsd`, `maxBudgetUsd`, `minBids` or `maxBids` are filtered before billing and cost nothing,
as do sample rows, diagnostics and a run that finds nothing.

### Speed

Real runs on Apify, 1 GB, no proxy:

| Rows | With client details | Time |
|---|---|---|
| 5 | yes | 3.8 s |
| 250 | yes | 27 s |
| 600 | yes | 61 s |
| 100 | no | 10 s |

Client details cost one extra request per project. Turn `includeClientDetails` off and a run is
roughly three times faster.

### Filters

Server-side (free, narrows the search before anything is fetched):

- `searchQuery` - free text over title, description and skills.
- `skills` - exact skill names, slugs or ids, such as `["PHP","Logo Design"]`.
- `projectType` - fixed or hourly.
- `upgrades` - featured / sealed / urgent / NDA.
- `sortBy` - newest first, or most bids first.

Client-side (applied after fetching; **dropped rows are never charged**):

- `minBudgetUsd` / `maxBudgetUsd` — compared in USD per project.
- `minBids` / `maxBids` — set `maxBids: 5` to find fresh work before the pile-on.
- `clientCountries` — `["US","GB"]` or `["United States"]`.

Why the last group is client-side: Freelancer's `max_avg_price` parameter is a relevance hint, not
a filter (with `max_avg_price=100`, 34 of 50 returned projects were above it), `min_avg_price`
filters in the project's own currency so "500" means 500 INR on an INR project, and `countries[]`
is accepted and then ignored (0 of 30 returned rows carried any country). Doing it here gives an
exact, predictable answer instead of an approximate one.

### Limits you should know about

- **~5,000 projects per search.** Freelancer's API stops paging at an offset of roughly 4,990. Past
  that every page repeats the last one, even when its own `total_count` claims more. The actor
  detects the wall, logs it and stops. To go deeper, split the job into several narrower
  searches (by skill, by keyword, by project type) rather than one huge one.
- **100 projects per request** is the API's real page size, and it often returns 97-99 for a
  requested 100 because it filters rows out after applying the limit.
- **Active projects only.** Closed, awarded and completed projects are not reachable without a
  logged-in Freelancer account.
- **Bids themselves are not included.** The individual bid list needs authentication. You get the
  count and the average, not who bid what.

### What this actor does not do

- It does not scrape freelancer *profiles*, only projects.
- It does not place bids, post projects, or touch your Freelancer account in any way. It never
  logs in.
- It does not return contest listings, only projects.
- It cannot see sealed bid amounts. That is the point of a sealed project. `isSealed` tells you the
  project is sealed; `bidCount` still works.
- It does not guess. If a client has no rating, the row says `clientRating: 0` and
  `clientReviewCount: 0` rather than inventing a number.

### Example input

Fresh WordPress work under $500 with fewer than 10 bids, from clients in the US or UK:

```json
{
  "searchQuery": "wordpress",
  "maxBudgetUsd": 500,
  "maxBids": 10,
  "clientCountries": ["US", "GB"],
  "maxItems": 200
}
```

Every hourly design project, newest first, without the client lookup (faster):

```json
{
  "skills": ["Graphic Design", "Logo Design"],
  "projectType": "hourly",
  "includeClientDetails": false,
  "maxItems": 500
}
```

### Example output

```json
{
  "projectId": 40634950,
  "title": "DNS Configuration and Testing for SMTP Providers",
  "projectUrl": "https://www.freelancer.com/projects/DNS-Configuration-Testing-for-SMTP",
  "projectType": "fixed",
  "budgetType": "fixed_price",
  "budgetMin": 10,
  "budgetMax": 15,
  "budgetCurrency": "USD",
  "budgetMinUsd": 10,
  "budgetMaxUsd": 15,
  "bidCount": 41,
  "averageBid": 18.22,
  "averageBidUsd": 18.22,
  "skills": ["System Admin", "Linux", "DNS", "Amazon Web Services", "Web Hosting"],
  "isSealed": false,
  "isFeatured": false,
  "clientCountry": "United States",
  "clientCountryCode": "US",
  "clientCity": "Kansas City",
  "clientRating": 5,
  "clientReviewCount": 1,
  "clientPaymentVerified": true,
  "postedAt": "2026-08-08T23:16:03.000Z",
  "bidsCloseAt": "2026-08-15T23:16:03.000Z"
}
```

### FAQ

**Is there a free Freelancer.com API?**
Yes. Freelancer publishes a REST API at `www.freelancer.com/api/projects/0.1/`, and the active
project search works without an OAuth token. What it will *not* give an anonymous caller is the
employer: `owner_id` comes back `null` on every row and the `users` map is always empty. This actor
fills that gap using the endpoint Freelancer's own project pages call for the employer panel, which
is why you get client country and rating here without logging in.

**Do I need a Freelancer account or API key?**
No. Nothing to sign up for, nothing to paste in.

**How many projects can I get in one run?**
About 5,000 per search. That's Freelancer's own paging wall, not a limit imposed here. Run several
narrower searches to cover more.

**Can I monitor new projects for a keyword?**
Yes. Schedule the actor with a `searchQuery` and `sortBy: "newest"`, and de-duplicate on
`projectId`. Freelancer posts thousands of projects a day, so a 15-minute schedule with
`maxItems: 100` keeps up comfortably.

**Why is the client rating 0 on so many rows?**
Because roughly two thirds of Freelancer clients have never received a review. That's a real 0,
not a missing value, so check `clientReviewCount` alongside it.

**Does it include the bids or the freelancers who bid?**
No. Freelancer requires authentication for the bid list. You get `bidCount` and `averageBid`.

**Is the budget the total or per hour?**
Read `budgetType`. `fixed_price` means the whole project; `hourly_rate` means per hour. 24% of
live projects are hourly, so this is not an edge case.

**Can I filter by client country?**
Yes, with `clientCountries`. It's applied after the client lookup, because Freelancer's own
`countries[]` parameter does nothing. Filtered-out projects are not charged.

**What does it cost?**
$0.45 per 1,000 projects, plus a $0.001 start fee per run. Rows that your filters drop, sample rows
and error rows are never charged.

**Is scraping Freelancer.com legal?**
This actor reads only public, logged-out project listings through Freelancer's own public API. It
collects no private data and does not log in. You're responsible for how you use the output.
Check Freelancer's terms and your local rules, especially before contacting clients in bulk.

# Actor input Schema

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

Free-text search across active Freelancer.com projects, e.g. "wordpress", "logo design", "python scraper". Leave empty to take the newest projects across the whole site.

## `skills` (type: `array`):

Only return projects tagged with these Freelancer skills. Use the exact skill name shown on the site ("PHP", "Logo Design", "Data Entry"), its URL slug ("web-design") or its numeric skill id. This is a real server-side filter, so it is the cheapest way to narrow a search.

## `projectType` (type: `string`):

Fixed-price projects quote a total budget; hourly projects quote an hourly rate. Every row states which in its budgetType field.

## `upgrades` (type: `array`):

Paid listing upgrades. These are rare — in a 994-project sample, featured 0.5%, sealed 0.5%, urgent 0.6%, NDA 0.4% — so selecting one will return very few rows.

## `maxItems` (type: `integer`):

Hard cap on rows returned. You are charged only for rows you receive. Freelancer's own API stops paging at roughly 5,000 projects per search, so that is the practical ceiling for one run.

## `includeClientDetails` (type: `boolean`):

Adds the client's country, city, star rating, review count, member-since date and verification flags. This costs one extra request per project, so a large run is slower with it on. Country is present on ~100% of projects; a star rating only on ~32%, because most Freelancer clients have no reviews yet.

## `clientCountries` (type: `array`):

Keep only projects whose client is in one of these countries. Accepts ISO codes ("US", "GB", "AU") or full names ("United States"). Filtered here, after the client lookup — Freelancer's own countries\[] parameter is accepted by the API but does nothing. Dropped projects are never charged.

## `minBudgetUsd` (type: `integer`):

Keep only projects whose budget range reaches this amount. Compared in USD using the exchange rate Freelancer returns with each project, so an INR or GBP project is converted before comparison. Applied here rather than server-side, because Freelancer's max\_avg\_price parameter is a relevance hint, not a filter. Dropped projects are never charged.

## `maxBudgetUsd` (type: `integer`):

Keep only projects whose budget range starts at or below this amount, in USD.

## `minBids` (type: `integer`):

Keep only projects with at least this many bids.

## `maxBids` (type: `integer`):

Keep only projects with at most this many bids. Useful for finding fresh, low-competition work: set it to 5.

## `sortBy` (type: `string`):

Newest first is Freelancer's default ordering. Most bids first surfaces the busiest projects.

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

Optional. Freelancer.com's public API answers the actor's own container address directly, so no proxy is needed or used by default. Set one only if you must exit from a specific network.

## Actor input object example

```json
{
  "searchQuery": "wordpress",
  "skills": [],
  "projectType": "any",
  "upgrades": [],
  "maxItems": 50,
  "includeClientDetails": true,
  "clientCountries": [],
  "sortBy": "newest",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (type: `string`):

One row per project in the default dataset: title, description, fixed or hourly budget with currency, bid count, average bid, skills, client country and rating, sealed and featured flags and the project URL. Empty or blocked runs return a single uncharged row instead.

# 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": "wordpress",
    "skills": [],
    "projectType": "any",
    "upgrades": [],
    "maxItems": 50,
    "includeClientDetails": true,
    "clientCountries": [],
    "sortBy": "newest",
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/freelancer-com-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": "wordpress",
    "skills": [],
    "projectType": "any",
    "upgrades": [],
    "maxItems": 50,
    "includeClientDetails": True,
    "clientCountries": [],
    "sortBy": "newest",
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("dami_studio/freelancer-com-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 '{
  "searchQuery": "wordpress",
  "skills": [],
  "projectType": "any",
  "upgrades": [],
  "maxItems": 50,
  "includeClientDetails": true,
  "clientCountries": [],
  "sortBy": "newest",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call dami_studio/freelancer-com-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/freelancer-com-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/htemfZI2izOcxs5Av/builds/kXvwPkhJFcscb5Tzq/openapi.json
