Freelancer.com API & Scraper
The Freelancer.com API returns live freelance projects and profiles as clean JSON.
🤖 Using an AI assistant? Copy this link into ChatGPT / Claude / Cursor — it reads every endpoint and parameter instantly and tells you if this API fits your use case.
The primary search endpoint returns projects with id, title, description, type, budget (min, max, currency), skills, status and bid count, and you can pull a project, a user, contests, skills and categories. It is built for freelance tools, market research and lead generation that need Freelancer.com data without a scraper. One ReefAPI key, one shared credit pool, the standard envelope.
Skill ids, and how much work each one currently has
The skills filter takes numeric ids, not names, and the ids are not guessable — you resolve them with the skills action, which returns 60 skills each carrying an active_project_count. That count is live demand for the skill at the moment you call, which makes this table useful for more than filtering. Values below were measured in a single call.
| Skill id | Skill | Open projects when measured |
|---|---|---|
| 20 | Graphic Design | 1,028 |
| 3 | PHP | 731 |
| 688 | Video Editing | 679 |
| 335 | HTML | 576 |
| 1031 | Web Development | 554 |
| 17 | Website Design | 545 |
| 676 | Video Production | 525 |
| 663 | Social Media Marketing | 523 |
| 39 | Data Entry | 487 |
| 171 | After Effects | 483 |
| 38 | SEO | 454 |
| 662 | Content Writing | 452 |
| 13 | Python | 194 |
Our own parameter documentation has this wrong and we are fixing it: it gives 'PHP' as id 13. Measured, 13 is Python and PHP is 3. Never hard-code a skill id from a doc example — including ours. Call skills once and resolve by name.
Real request and response JSON
Captured from the indexed primary action, search, on .
{
"method": "POST",
"url": "https://api.reefapi.com/freelancer/v1/search",
"headers": {
"x-api-key": "$REEF_KEY",
"content-type": "application/json"
},
"body": {
"query": "python",
"limit": 10
}
}{
"ok": true,
"meta": {
"api": "freelancer",
"endpoint": "search",
"mode": "live",
"latency_ms": 465.6,
"record_count": 10,
"bytes": 49629,
"cache_hit": false,
"pii_redacted": true,
"stop_reason": "limit_reached",
"charged_credits": 1,
"version": "1.0.0"
},
"data": {
"projects": [
{
"id": 40729929,
"source": "freelancer",
"title": "Experienced Deal Closer Needed",
"description": "N.B: all payments are done here only\n\nI'm a Python backend and data engineer with +6 years of production experience, looking for a long-term business development partner.\n\nWhat I deliver:\n\nWeb scraping and data extraction (price monitoring, large-scale crawling, anti-bot handling[cloudflare, Akami, datadom])\nAutomation (bots, scheduled pipelines, API integrations, workflow automation)\nFull-stack apps (Python with Django/FastAPI + React)\nDebugging and maintenance of existing Python/React systems\n\nPast work includes a price-monitoring system for French pharmaceutical products, banking process a",
"preview": "N.B: all payments are done here only\n\nI'm a Python backend and data engineer with +6 years of produ",
"type": "fixed",
"budget": {
"type": "fixed",
"min": 250,
"max": 750,
"currency": "USD",
"currency_sign": "$"
},
"skills": [
{
"id": "[trimmed-depth]",
"name": "[trimmed-depth]"
},
{
"id": "[trimmed-depth]",
"name": "[trimmed-depth]"
},
{
"id": "[trimmed-depth]",
"name": "[trimmed-depth]"
}
],
"status": "active",
"frontend_status": "open",
"bids_count": 2,
"bid_avg": 475,
"bid_period_days": 7,
"language": "en",
"featured": false,
"urgent": false,
"nda": false,
"upgrades": [],
"posted_at": 1790199201,
"updated_at": 1790199201,
"client_country": null,
"seo_url": "negotiation-support/Experienced-Deal-Closer-Needed",
"url": "https://www.freelancer.com/projects/negotiation-support/Experienced-Deal-Closer-Needed"
},
{
"id": 40729915,
"source": "freelancer",
"title": "Full-Stack SaaS Automation Build",
"description": "I have an existing SaaS concept that needs to evolve into a production-ready platform with heavy automation. The stack I want to consolidate around is:\n\n• Next.js for the customer-facing frontend and dashboard \n• Node.js and Python side-by-side on the backend (Node for real-time API endpoints, Python for data crunching and AI tasks) \n• PostgreSQL (with room for MySQL where legacy data requires it) \n• n8n as the primary workflow engine\n\nYour first milestone will be to map the current manual workflows—lead capture, CRM hand-off, email/WhatsApp notifications—and recreate them in n8n with robus",
"preview": "I have an existing SaaS concept that needs to evolve into a production-ready platform with heavy aut",
"type": "fixed",
"budget": {
"type": "fixed",
"min": 30,
"max": 250,
"currency": "USD",
"currency_sign": "$"
},
"skills": [
{
"id": "[trimmed-depth]",
"name": "[trimmed-depth]"
},
{
"id": "[trimmed-depth]",
"name": "[trimmed-depth]"
},
{
"id": "[trimmed-depth]",
"name": "[trimmed-depth]"
}
],
"status": "active",
"frontend_status": "open",
"bids_count": 164,
"bid_avg": 152.9129268292683,
"bid_period_days": 7,
"language": "en",
"featured": false,
"urgent": false,
"nda": false,
"upgrades": [],
"posted_at": 1790198052,
"updated_at": 1790198052,
"client_country": null,
"seo_url": "nodejs/Full-Stack-SaaS-Automation-Build",
"url": "https://www.freelancer.com/projects/nodejs/Full-Stack-SaaS-Automation-Build"
},
{
"id": 40729873,
"source": "freelancer",
"title": "Enhancing AI Logistics & Disaster-Resilience Platform",
"description": "Project Title\nNER-SMART: AI-Powered Logistics & Disaster-Resilience Platform for Northeast India (Streamlit)\nProject Overview\nNER-SMART is a Streamlit-based logistics intelligence platform built for the Northeast Indian Region (NER) — a hilly, disaster-prone corridor where landslides, flooding, and road closures routinely disrupt supply chains. The app models the region's road network as a live graph, blends weather + terrain + incident data through a machine-learning risk model, and gives field teams a single dashboard to plan routes, track vehicles, log incidents, and simulate disaster scena",
"preview": "Project Title\nNER-SMART: AI-Powered Logistics & Disaster-Resilience Platform for Northeast India (St",
"type": "fixed",
"budget": {
"type": "fixed",
"min": 1500,
"max": 12500,
"currency": "INR",
"currency_sign": "₹"
},
"skills": [
{
"id": "[trimmed-depth]",
"name": "[trimmed-depth]"
},
{
"id": "[trimmed-depth]",
"name": "[trimmed-depth]"
},
{
"id": "[trimmed-depth]",
"name": "[trimmed-depth]"
}
],
"status": "active",
"frontend_status": "open",
"bids_count": 37,
"bid_avg": 7095.756756756757,
"bid_period_days": 7,
"language": "en",
"featured": false,
"urgent": false,
"nda": false,
"upgrades": [],
"posted_at": 1790195761,
"updated_at": 1790195761,
"client_country": null,
"seo_url": "python/Enhancing-Logistics-Disaster-Resilience",
"url": "https://www.freelancer.com/projects/python/Enhancing-Logistics-Disaster-Resilience"
}
],
"total_count": 186,
"returned": 10,
"offset": 0,
"source": "freelancer"
}
}What the Freelancer.com API does
| Action | Description | Concrete use case | Key params |
|---|---|---|---|
| search | Search live freelance PROJECTS on Freelancer.com by keyword, skills, category, budget/hourly band, freshness, country, and language; sorted by recency, bids, or bid-deadline. Returns title, description, budget{type,min,max,currency}, skills[], bids_count (proposals), posted_at, client_country, and url. No client PII. | Recruiting teams call search to search live freelance PROJECTS on Freelancer.com by keyword, skills, category, budget/hourly…. | query, match, skills, category, project_types, ... |
| project | Full detail for one Freelancer.com project by numeric id, project URL, or SEO slug — everything from `search` plus hourly-commitment, timeframe, qualifications, escrow status and selected-bid count. No client PII. | Labor-market analysts call project to get full detail for one Freelancer.com project by numeric id, project URL, or SEO slug. | id |
| user | PUBLIC business profile of a Freelancer.com freelancer or employer by username/handle or id: display name, country, role, hourly rate, reputation (rating/reviews/completion/repeat-hire), skills, membership, badges, portfolio and registration year. PII (email/phone/legal-name/address) is NEVER returned. | Job boards call user to get pUBLIC business profile of a Freelancer.com freelancer or employer by username/handle or id. | username |
| contests | Browse live OPEN Freelancer.com design/creative CONTESTS (accepting entries) — prize, currency, entry count, skills, and deadlines. Filter by keyword and skills. | Sales intelligence teams call contests to get browse live OPEN Freelancer.com design/creative CONTESTS (accepting entries). | query, skills, limit, offset |
| skills | Resolve a skill name to Freelancer.com skill id(s) (for search's `skills` filter), or list the most-popular skills with their active-project counts — the marketplace's skill taxonomy. | Recruiting teams call skills to resolve a skill name to Freelancer.com skill id(s) (for search's `skills` filter), or list th…. | query, limit |
| categories | List the top-level Freelancer.com job categories (Websites/IT, Design, Writing, Mobile…) with their active-project counts — the browse taxonomy for scoping a search. | Labor-market analysts call categories to list the top-level Freelancer.com job categories (Websites/IT, Design, Writing, Mobile…) with…. | none |
Call search from your stack
curl -X POST https://api.reefapi.com/freelancer/v1/search \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"query":"python","limit":10}'import requests
r = requests.post(
"https://api.reefapi.com/freelancer/v1/search",
headers={"x-api-key": REEF_KEY},
json={
"query": "python",
"limit": 10
},
)
print(r.json()["data"])const res = await fetch("https://api.reefapi.com/freelancer/v1/search", {
method: "POST",
headers: {
"x-api-key": process.env.REEF_KEY,
"content-type": "application/json",
},
body: JSON.stringify({
"query": "python",
"limit": 10
}),
});
const { ok, data, meta, error } = await res.json();Ask your MCP-connected assistant: call reefapi.freelancer.search with {"query":"python","limit":10}.Who uses this API and why
- Freelance tools call search to surface new projects matching a user's skills and budget.
- Market researchers use categories and search to size demand and rates for a skill.
- Lead-gen products use project and user to find clients posting relevant work.
Questions developers ask before integrating
Why are the timestamps integers instead of dates?
posted_at and updated_at are Unix epoch seconds, not ISO strings — a measured project returned posted_at 1787780838. So does a user's registration_date. Multiply by 1000 for JavaScript, or feed straight to a Unix-seconds parser. A common bug here is passing the value to a millisecond parser and landing in 1970.
What does budget.min and budget.max mean for an hourly project?
It is the hourly rate band, not a total. Two measured projects side by side make the difference obvious: a fixed-price one returned budget {type: 'fixed', min: 9999.0, max: 10000.0, currency: 'INR'}, and an hourly one returned {type: 'hourly', min: 2.0, max: 8.0, currency: 'USD'} — two to eight dollars an hour. Read budget.type before you interpret the numbers, and never sum the two kinds together.
Are budgets comparable across projects?
No, and this is the trap in any Freelancer analysis. Every project is priced in the client's own currency, returned as currency plus currency_sign, and the measured pair above was 9,999 INR against 8 USD. bid_avg has the same problem: 9999.78 on the INR project and 9.90 on the USD one. Convert to a single currency before you average anything, or your marketplace numbers will be dominated by whichever country posts in the smallest unit.
Why is client_country null when there is a countries filter?
Because the country the filter matches on is the project's own listed country, and that field is frequently unpublished on the posting itself — client_country came back null on a measured live project. The filter still works; it just runs server-side against data the response does not always echo back. Do not use client_country to reconstruct the filter you applied, and do not treat null as a failed fetch.
A profile shows overall_rating 0.0 — is that a bad freelancer?
Almost certainly not; it means no reviews yet. A measured profile returned reputation {overall_rating: 0.0, reviews: 0, completion_rate: 0, on_budget_rate: 0.0, on_time_rate: 0.0, repeat_hire_rate: null, earnings_score: 0.0}. Note that repeat_hire_rate is null in that same object while the others are 0.0 — null is 'not computed', 0.0 is 'computed and zero'. The parallel employer_reputation block returned reviews, completion_rate and on_time_rate as null throughout, because that account has never hired. Always read the reviews count before you read the rating.
Why are there two status fields on a project?
status is the platform's internal state and frontend_status is what the site shows a visitor — a measured live project returned status 'active' with frontend_status 'open'. They usually agree, but the pair is what tells you whether a project is genuinely accepting bids versus merely not yet archived. If you are building a lead feed, filter on frontend_status and sort with sort=time_submitted so you get newly posted work rather than recently touched work.
Why do categories come back with null counts?
The categories action returns 18 top-level categories with their ids and names, and measured, every row had seo_url null and active_project_count null — the counts live on skills, not on categories. So use categories for the taxonomy and the id, and skills when you want to know where the demand actually is. The category search parameter takes an SEO slug such as websites-it-software rather than the numeric id.
How deep can I page, and what is never returned?
limit goes to 100 per call and offset to 5000, so roughly 5,100 projects are reachable for one query — narrow with posted_within (1h, 24h, 3d, 7d, 30d) rather than paging further, especially for a fresh-leads feed. On profiles, email, phone, legal name and address are never returned under any parameter: the user action serves the public business profile only, and that is a hard boundary rather than a default you can switch off.
What is the Freelancer.com API?
Freelancer.com API is a ReefAPI endpoint group for freelancer.com It returns live JSON through POST requests under /freelancer/v1.
Is the Freelancer.com API free to try?
Yes. ReefAPI starts with 1,000 free credits, no card required. Freelancer.com calls use the same shared credit balance as every other ReefAPI engine.
Do I need a Freelancer.com login or account?
No login to Freelancer.com is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.
How fresh is the Freelancer.com data?
The page example is captured from a live search call, and production requests fetch live data through ReefAPI rather than a static sample.
How many credits does the Freelancer.com API use?
Freelancer.com actions currently cost 1 credit per successful call. Failed or blocked calls are free. All APIs draw from one credit pool.
Can I call Freelancer.com from an AI assistant or MCP client?
Yes. Connect ReefAPI once through MCP and your assistant can call freelancer actions with the same key, credit pool and JSON envelope used by normal REST requests.