Upwork APIupwork.com ↗
Search Upwork freelancers by keyword. Returns profiles with hourly rates, job success scores, skills, location, and earnings data via a single endpoint.
What is the Upwork API?
The Upwork API exposes one endpoint — search_freelancers — that returns up to 50 freelancer profiles per page across 17 structured fields including hourly rate, currency, job success score, skills array, city, country, and total results count. Pass any keyword or skill term to retrieve paginated, ranked freelancer listings directly from Upwork's marketplace.
curl -X GET 'https://api.parse.bot/scraper/59193041-dabe-405d-8d1b-570a0b3a553e/search_freelancers?page=1&query=python+developer&per_page=5' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace upwork-com-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""Walkthrough: Upwork Freelancer Search — find talent by keyword, inspect profiles."""
from parse_apis.upwork_freelancer_search_api import Upwork, FreelancerSearchFailed
client = Upwork()
# Search for Python developers, cap at 5 results total
for freelancer in client.freelancers.search(query="python developer", per_page=5, limit=5):
print(freelancer.name, freelancer.title, freelancer.hourly_rate, freelancer.country)
# Drill into one result for detailed inspection
top = client.freelancers.search(query="data engineer", per_page=3, limit=3).first()
if top:
print(top.name, top.skills, top.job_success_score, top.total_earnings)
# Typed error handling around a search call
try:
result = client.freelancers.search(query="react native", limit=1).first()
if result:
print(result.name, result.profile_url)
except FreelancerSearchFailed as exc:
print(f"Search failed: {exc}")
print("exercised: freelancers.search / .first() / typed error catch")
Full-text search over Upwork's freelancer talent pool. Returns paginated results with detailed profile information including skills, hourly rate, job success score, location, and earnings. Pagination via integer page counter; each page returns up to per_page results. The query matches freelancer titles, descriptions, and skills.
| Param | Type | Description |
|---|---|---|
| page | integer | Page number (1-based) |
| query | string | Search keyword(s) to find freelancers by title, description, or skills |
| per_page | integer | Number of results per page (1-50) |
{
"type": "object",
"fields": {
"page": "integer - current page number",
"query": "string - the search query used",
"per_page": "integer - results per page",
"freelancers": "array of freelancer objects with name, title, description, profile_url, portrait_url, hourly_rate, currency, country, city, state, timezone, skills, job_success_score, top_rated, top_rated_plus, total_hours, total_earnings, total_completed_jobs, vetted, id_verified, hide_earnings, hide_jss, ciphertext",
"total_pages": "integer - total number of pages available",
"results_count": "integer - number of freelancer results returned on this page",
"total_results": "integer - total matching freelancers"
}
}About the Upwork API
What the API Returns
The search_freelancers endpoint accepts a query string (skill name, job title, or any keyword) and returns an array of freelancer objects. Each object includes name, title, a short description, a direct profile_url, hourly_rate with currency, country and city for location, a skills array listing the freelancer's tagged competencies, and a job_success_score reflecting their historical client rating on the platform.
Pagination
Results are paginated using page (1-based integer) and per_page (1–50). The response also returns total_results (total matching freelancers for the query), total_pages, and results_count (records returned in the current page). This lets you walk through large result sets or build an interface that shows ranked candidates across multiple pages.
Data Coverage and Freshness
The API reflects Upwork's public freelancer marketplace. Profiles with private or restricted visibility on Upwork may not appear in results. Fields like hourly_rate and job_success_score correspond to what the freelancer has publicly set or earned on the platform at the time of the request. Availability status and recent activity are not included in the current response shape.
The Upwork API is a managed, monitored endpoint for upwork.com — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when upwork.com changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official upwork.com API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Build a vendor sourcing tool that queries freelancers by skill and compares hourly rates across locations
- Aggregate job success scores to rank candidates programmatically before manual review
- Enrich a recruiter CRM with Upwork profile URLs, titles, and skills arrays pulled by keyword
- Generate a market-rate report by querying multiple skill keywords and averaging returned hourly_rate values
- Monitor how many freelancers list a given emerging skill using the total_results count across queries
- Power an internal talent finder that lets non-technical staff search Upwork without accessing the site directly
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 100 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
One credit = one API call regardless of which marketplace API you call. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does Upwork have an official developer API?+
What does the job_success_score field represent?+
Can I filter results by hourly rate range, location, or specific skills?+
query string for filtering. Results reflect Upwork's default relevance ranking for that query. Filtering by hourly_rate range, specific country, or skills subset is not available in the current API. You can fork the API on Parse and revise it to add filter parameters targeting those fields.Are freelancer earnings or total contract history included?+
hourly_rate, job_success_score, and skills. Detailed earnings history, total contract value, or individual client review text are not currently returned. You can fork the API on Parse and revise it to add a profile-detail endpoint that exposes deeper earnings and review data.How many results can I retrieve per request and is there a cap on total pages?+
per_page accepts values from 1 to 50. The total_pages and total_results fields in each response tell you the full scope of available results for a given query. Deep pagination into very large result sets may return fewer unique profiles as Upwork's public-facing search typically surfaces the most relevant candidates in earlier pages.