Truelancer.com API & Scraper
The Truelancer.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, category and bid count, and you can pull a project and a user. It is built for freelance tools, market research and lead generation that need Truelancer data without a scraper. One ReefAPI key, one shared credit pool, the standard envelope.
Addressing a project, and which fields only the detail action fills
Two things send most first calls into a 404. The project id in a search row is not accepted by the project action on its own, and the slug format the parameter description shows is not the one that resolves. Everything below was measured on live calls: the search action for 'logo design' and 'wordpress', project 655630 (Professional Brand Identity Design), and the profiles webdev, johnsmith, designer, rahulkumar and priya.
| Field | Measured shape | What to do with it |
|---|---|---|
| projects[].id | 6-digit integer, e.g. 655630, which is also the number on the end of the URL slug | Do not pass it to the project action on its own. A bare numeric id is rejected with INVALID_PARAM. |
| project action, id param | The full https URL works, and so does the bare slug 'professional-brand-identity-design-655630' | The prefixed form 'freelance-project/<slug>-<id>' returned NOT_FOUND (HTTP 404) in our tests, so use the URL or the bare slug. |
| budget | Object {type, min, max, currency}, not a string. type is 'fixed' or 'hourly'. | min equals max on every row we sampled, because Truelancer publishes one figure rather than a range. Every sampled row was USD. |
| skills | Array of {id, name} objects, not strings. Ids we saw ran from 1 to 3037. | 32 = Logo Designers, 35 = Graphic Designers, 104 = Data Entry Operators, 429 = Artificial Intelligence Engineers, 2674 = Video editing. |
| posted_at | Unix epoch seconds, not ISO-8601. 1787415416 is 2026-08-22T16:16:56Z. | Multiply by 1000 before handing it to a JavaScript Date. |
| status | 'Active' or 'Freezed and Awarded' | An already-awarded project stays in search results, so filter on status if you only want biddable work. |
| category, client_country, client | null on every search row we pulled | All three are filled by the project action: category 'Graphic Design & Multimedia', client_country 'Egypt', client {country, country_code, verified, total_spent, jobs_posted, avg_rating_given}. |
| detail.end_date | Date only, '2026-09-14' | The bidding deadline. It is unrelated to posted_at and only exists on the project action. |
| user, username param | A handle ('webdev') or a full profile URL both resolve | The numeric user id is separate from the handle: webdev is id 112250. An unknown handle returns NOT_FOUND. |
| user.role | 'freelancer' or 'employer' | The same action resolves client accounts, not only freelancers. Check role before treating a record as a freelancer profile. |
The poster's name is never returned. What you get about a client is coarse: country, a verified flag, total_spent and jobs_posted. Note also that data.total_count is not a result total. Measured at offsets 0, 15, 30 and 45 with limit 15 it read 15, 30, 45 and 60, so it tracks how far you have paged. Raise offset until returned comes back smaller than the limit you asked for.
Real request and response JSON
Captured from the indexed primary action, search, on .
{
"method": "POST",
"url": "https://api.reefapi.com/truelancer/v1/search",
"headers": {
"x-api-key": "$REEF_KEY",
"content-type": "application/json"
},
"body": {
"query": "design",
"limit": 8
}
}{
"ok": true,
"meta": {
"api": "truelancer",
"endpoint": "search",
"mode": "live",
"latency_ms": 5048,
"record_count": 8,
"bytes": 283616,
"cache_hit": false,
"pii_redacted": true,
"stop_reason": "limit_reached",
"charged_credits": 1,
"version": "1.0.0"
},
"data": {
"projects": [
{
"id": 659425,
"source": "truelancer",
"title": "React Developer for Responsive Admin Dashboard is about creat a responsive react dashboard",
"description": "We are seeking a skilled React developer to build a responsive and fast admin dashboard for managing client data.Project Scope & Key Tasks:- Design an intui...",
"preview": "We are seeking a skilled React developer to build a responsive and fast admin dashboard for managing client data.Project Scope & Key Tasks:- Design an intui...",
"type": "fixed",
"budget": {
"type": "fixed",
"min": 20,
"max": 20,
"currency": "USD"
},
"skills": [
{
"id": "[trimmed-depth]",
"name": "[trimmed-depth]"
},
{
"id": "[trimmed-depth]",
"name": "[trimmed-depth]"
},
{
"id": "[trimmed-depth]",
"name": "[trimmed-depth]"
}
],
"category": null,
"status": "Active",
"bids_count": 12,
"posted_at": 1790180664,
"client_country": null,
"client": null,
"featured": false,
"urgent": true,
"nda": false,
"url": "https://www.truelancer.com/freelance-project/react-developer-for-responsive-admin-dashboard-is-about-creat-a-responsive-react-dashboard-659425",
"seo_url": "https://www.truelancer.com/freelance-project/react-developer-for-responsive-admin-dashboard-is-about-creat-a-responsive-react-dashboard-659425"
},
{
"id": 659389,
"source": "truelancer",
"title": "Smart Glasses Research Study – Los Angeles, USA [ In-Person ]",
"description": "In-Person User Study – Los Angeles, USAWe are looking for participants in Los Angeles, California for a one-day, in-person user study conducted at a designated...",
"preview": "In-Person User Study – Los Angeles, USAWe are looking for participants in Los Angeles, California for a one-day, in-person user study conducted at a designated...",
"type": "hourly",
"budget": {
"type": "hourly",
"min": 20,
"max": 20,
"currency": "USD"
},
"skills": [],
"category": null,
"status": "Active",
"bids_count": 0,
"posted_at": 1790163625,
"client_country": null,
"client": null,
"featured": false,
"urgent": false,
"nda": false,
"url": "https://ai.truelancer.com/apply/160?utm_source=marketplace",
"seo_url": "https://ai.truelancer.com/apply/160?utm_source=marketplace"
},
{
"id": 659388,
"source": "truelancer",
"title": "Freelance Architect & Digital Media Specialist",
"description": "We are seeking a skilled and creative freelancer to provide a comprehensive range of architectural, design, and digital media services.Required services include...",
"preview": "We are seeking a skilled and creative freelancer to provide a comprehensive range of architectural, design, and digital media services.Required services include...",
"type": "fixed",
"budget": {
"type": "fixed",
"min": 51,
"max": 51,
"currency": "USD"
},
"skills": [
{
"id": "[trimmed-depth]",
"name": "[trimmed-depth]"
},
{
"id": "[trimmed-depth]",
"name": "[trimmed-depth]"
},
{
"id": "[trimmed-depth]",
"name": "[trimmed-depth]"
}
],
"category": null,
"status": "Active",
"bids_count": 5,
"posted_at": 1790163440,
"client_country": null,
"client": null,
"featured": true,
"urgent": true,
"nda": false,
"url": "https://www.truelancer.com/freelance-project/freelance-architect-digital-media-specialist-659388",
"seo_url": "https://www.truelancer.com/freelance-project/freelance-architect-digital-media-specialist-659388"
}
],
"total_count": 15,
"returned": 8,
"offset": 0,
"source": "truelancer"
}
}What the Truelancer.com API does
| Action | Description | Concrete use case | Key params |
|---|---|---|---|
| search | Search live freelance PROJECTS on Truelancer.com by keyword. Returns title, description, budget{type,min,max,currency}, skills[], category, proposal count, posted_at, coarse client signals (country, verified, total spent), and the project url. No client PII (the poster's name is dropped). | Recruiting teams call search to search live freelance PROJECTS on Truelancer.com by keyword. | query, limit, offset |
| project | Full detail for one Truelancer.com project by URL or slug — everything from `search` plus views, end-date, tags, payment-verified flag, and proposal breakdown (received/active/shortlisted). No client PII. | Labor-market analysts call project to get full detail for one Truelancer.com project by URL or slug. | id |
| user | PUBLIC business profile of a Truelancer.com freelancer by handle or profile URL: display name, headline, country, hourly rate, skills, ratings (avg rating, reviews, five-star %, projects delivered, total earnings), membership and availability. PII (email/phone/legal-name/address) is NEVER returned. | Job boards call user to get pUBLIC business profile of a Truelancer.com freelancer by handle or profile URL. | username |
Call search from your stack
curl -X POST https://api.reefapi.com/truelancer/v1/search \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"query":"design","limit":8}'import requests
r = requests.post(
"https://api.reefapi.com/truelancer/v1/search",
headers={"x-api-key": REEF_KEY},
json={
"query": "design",
"limit": 8
},
)
print(r.json()["data"])const res = await fetch("https://api.reefapi.com/truelancer/v1/search", {
method: "POST",
headers: {
"x-api-key": process.env.REEF_KEY,
"content-type": "application/json",
},
body: JSON.stringify({
"query": "design",
"limit": 8
}),
});
const { ok, data, meta, error } = await res.json();Ask your MCP-connected assistant: call reefapi.truelancer.search with {"query":"design","limit":8}.Who uses this API and why
- Freelance tools call search to surface new Truelancer projects matching a user's skills.
- Market researchers use search to size demand and budgets for a service.
- Lead-gen products use project and user to find clients posting relevant work.
Questions developers ask before integrating
The search results have an id like 655630. Why does the project action reject it?
Truelancer's project page cannot be reached from the numeric id alone without a login, so the engine rejects a bare number with INVALID_PARAM rather than guessing. Pass either the full url from the search row, or the bare slug that ends in that number, for example 'professional-brand-identity-design-655630'. The form written as 'freelance-project/<slug>-<id>' came back NOT_FOUND in our tests.
Is the budget a number or a string?
It is a structured object: budget{type, min, max, currency}. type mirrors the project's own type field and is either 'fixed' or 'hourly'. On every project we sampled min and max were equal, because Truelancer's posting form takes a single figure rather than a range, and currency was USD throughout.
Why are category, client_country and client null in search results?
Truelancer's listing payload does not carry them; they come from the individual project page. Call the project action for any row you care about and you get category 'Graphic Design & Multimedia', detail.subcategory 'Brand Identity Packages', client_country 'Egypt', and a client object with country_code, verified, total_spent, jobs_posted and avg_rating_given.
What does status 'Freezed and Awarded' mean?
The client has picked a freelancer and the project is closed to new proposals. Those rows still appear in search results next to 'Active' ones, so if you are building a bidding or alerting tool, filter on status yourself. Those two were the only values we saw across the projects we sampled.
Are skills plain strings I can match on?
No. skills is an array of {id, name} objects, so skills[0].name is 'Logo Designers', not 'logo design'. The ids are stable Truelancer skill ids and make the better join key: 32 is Logo Designers, 35 Graphic Designers, 104 Data Entry Operators, 429 Artificial Intelligence Engineers. The same shape appears on a freelancer's profile.
Does the user action work for clients as well as freelancers?
Yes, and this surprises people. A handle resolves whichever account owns it, and the record carries a role field that reads 'freelancer' or 'employer'. Of five handles we probed, three were freelancers and two were employers, with organization_type 'Individual' or 'Company'. Check role before you treat a record as a freelancer.
How do I page through results, and can I trust total_count?
Page with offset, which accepts values up to 5000 and returned a fresh set of 15 at offsets 0, 15, 30 and 45. Do not read total_count as a result total: on those same four calls it read 15, 30, 45 and 60, so it tracks how far you have paged rather than how much exists. Keep raising offset until returned comes back smaller than the limit you asked for.
Is any client contact information returned?
No. The poster's name, email, phone and address are dropped before the response is built, and the same applies to freelancer profiles. What remains is business information: country and country code, a verified flag, total_spent, jobs_posted, ratings, hourly_rate, skills and the public profile URL.
What is the Truelancer.com API?
Truelancer.com API is a ReefAPI endpoint group for truelancer.com It returns live JSON through POST requests under /truelancer/v1.
Is the Truelancer.com API free to try?
Yes. ReefAPI starts with 1,000 free credits, no card required. Truelancer.com calls use the same shared credit balance as every other ReefAPI engine.
Do I need a Truelancer.com login or account?
No login to Truelancer.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 Truelancer.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 Truelancer.com API use?
Truelancer.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 Truelancer.com from an AI assistant or MCP client?
Yes. Connect ReefAPI once through MCP and your assistant can call truelancer actions with the same key, credit pool and JSON envelope used by normal REST requests.