# Upwork Freelancers Scraper - Hourly Rate & Earnings (`parseforge/upwork-freelancers-scraper`) Actor

Scrapes Upwork freelancer profiles by skill keyword. Returns a flat row with title, hourly rate, total earnings, job success score, and location.

- **URL**: https://apify.com/parseforge/upwork-freelancers-scraper.md
- **Developed by:** [ParseForge](https://apify.com/parseforge) (community)
- **Categories:** Jobs, Lead generation
- **Features:** Limited permissions
- **Stats:** 505 total users, 32 monthly users, 100.0% runs succeeded, 2 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $16.99 / 1,000 result items

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

[![ParseForge](https://raw.githubusercontent.com/ParseForge/apify-assets/main/banner-v4.webp)](https://apify.com/parseforge?fpr=vmoqkp)

### Upwork Freelancers Scraper

**Scrape Upwork freelancer profiles by skill, keyword, location, or a pasted Upwork search URL.** Each profile returns a permanent freelancer ID, the title, hourly rate, total earnings, job success score, hours and jobs worked, location, intro video link, and agency. No login or API key. Export to CSV, JSON, Excel, or XML.

**Pay only for results:** there is no start fee today, only a price per freelancer. From 3 October 2026 a run also carries the standard Apify start fee of $0.005 per GB of run memory, which is $0.005 per run at the default 1 GB.

Upwork's official API requires a developer account and restricts the depth of freelancer data you can pull. This actor reads the public search results directly, filtering by earned amount (including new freelancers with no earnings yet), hourly rate, job success, hours billed, Top Rated and Rising Talent badges, or specific countries and regions, and returns each matching profile in one consistent schema. Build a talent pipeline, analyze competitor skill sets, or populate a recruitment database without writing a single line of code.

| Who uses it | What they scrape Upwork for |
|---|---|
| Recruitment agencies | Build a searchable database of pre-vetted freelance talent for specific skill sets. |
| Market analysts | Track the supply and hourly rates of freelancers in a given niche over time. |
| Sales teams | Identify and qualify independent contractors who may need complementary tools or services. |
| Aspiring freelancers | Benchmark their own rates and skills against top earners in their category. |

### What it does

This Actor collects Upwork freelancer profiles by skill keyword and returns each one as a flat row with their title, rate, earnings, and location.

- 🔗 **Search URL input:** build a search on upwork.com, paste its address, and the actor applies the same keyword and filters.
- 🌱 **Earned amount filter:** find new freelancers with no earnings yet, or only those past $1, $100, $1k or $10k earned.
- 💲 **Rate, job success and hours:** set a minimum or maximum hourly rate, a minimum Job Success Score, or a minimum of hours billed.
- ⭐ **Badge filters:** restrict results to Top Rated, Top Rated Plus, or Rising Talent freelancers.
- 🌍 **Location targeting:** filter by continent, sub-region, or a specific country to find local talent.
- 🔁 **No repeats across runs:** turn on "Skip freelancers from earlier runs" and a repeated search returns only profiles you have not collected yet.
- 🆔 **Stable freelancer ID:** every row carries Upwork's `~01...` freelancer ID, which stays the same when a freelancer changes the username in their profile link.
- 🏢 **Agency details:** freelancers who belong to an agency come with the agency ID, name and page URL, plus every agency they are in.
- 🎬 **Intro video:** the YouTube link from the profile's video introduction, when the freelancer has one.
- 🔢 **Volume control:** set a precise maximum number of profiles to collect. Upwork shows at most 10,000 results per search, so larger pulls use several keywords in one run.
- 🙈 **Honest nulls:** when a freelancer hides their earnings, Upwork reports $0. The actor returns `totalEarnings: null` instead of a false $0, with `earningsHidden: true` when the profile's hours, Job Success Score or badge prove the earnings are hidden. A missing Job Success Score is `null`, not 0.

Results export to CSV, JSON, Excel, or XML, or straight from the API.

### What you can do with Upwork data

**🔍 Build a talent pipeline.**

A recruiter runs the actor daily for 'react developer' and filters by Top Rated Plus to maintain a fresh list of elite candidates.

**📊 Analyze freelance market rates.**

A market analyst scrapes 'python developer' across different regions to compare average hourly rates and inform a pricing report.

**🌎 Find local contractors.**

A project manager sets the country filter to 'Canada' and the skill to 'technical writer' to find nearby freelancers for an on-site contract.

**🌱 Reach new freelancers first.**

A tool vendor pastes `https://www.upwork.com/nx/search/talent/?q=copywriting&loc=united-states&revenue=0` to list US copywriters who have not landed a paid job yet, and offers them an onboarding deal.

**🔁 Work through a talent pool in batches.**

An outreach team pulls 1,000 new copywriters on Monday and another 1,000 on Tuesday with the same search and history name. Tuesday's run leaves out everyone Monday already delivered, so nobody gets contacted twice.

**📈 Monitor competitor skills.**

A freelancer scrapes their own niche to see which complementary skills top earners list and updates their own profile accordingly.

### Why choose this scraper

|  | What you get |
|---|---|
| **No API registration** | Access public freelancer data without a developer account or OAuth tokens. |
| **Fixed flat schema** | Every profile is normalized into the same columns for easy analysis. |
| **Flexible location filters** | Target freelancers by continent, sub-region, or a single country. |
| **Quality signals** | Filter by Top Rated and Top Rated Plus badges to isolate high-quality talent. |

### How it compares

This actor focuses exclusively on freelancer profiles, while the competitors listed below are designed for scraping Upwork job postings.

| Feature | ParseForge | Upwork Job Scraper | Upwork Job Extractor ⚡ | Upwork Jobs |
|---|---|---|---|---|
| Scrapes freelancer profiles | Yes | Not listed | Not listed | Not listed |
| Scrapes job postings | Not listed | Yes | Yes | Yes |
| Filter by Top Rated status | Yes | Not listed | Not listed | Not listed |
| Filter by freelancer location | Yes | Not listed | Not listed | Not listed |
| Returns freelancer hourly rate | Yes | Not listed | Not listed | Not listed |

### Configure the run

Drive the Actor with a skill or job title keyword, and apply Top Rated and location filters as each profile is read so only matches reach your dataset. The Input tab lists every parameter.

A first run with the defaults:

```json
{
  "searchQuery": "python developer",
  "maxItems": 10
}
```

Several keywords at once: separate them with commas. Each keyword is searched on its own and the
results are merged, so every freelancer is returned once even when two keywords both match them.

```json
{
  "searchQuery": "full stack developer, frontend developer, software engineer",
  "maxItems": 100
}
```

Paste a search you built on upwork.com. Keyword (`q`), location (`loc`), earned amount (`revenue`), hourly rate (`hourly_rate`), job success (`nss`), hours billed (`hours`) and the Top Rated, Top Rated Plus and Rising Talent badges carry over:

```json
{
  "searchUrl": "https://www.upwork.com/nx/search/talent/?q=copywriting&loc=united-states&revenue=0",
  "maxItems": 100
}
```

Or set the same filters by hand:

```json
{
  "searchQuery": "copywriting",
  "country": "United States",
  "earnings": "none",
  "maxItems": 100
}
```

Run the same search again later without getting anyone twice. Every run that uses the same history name skips the freelancers earlier runs delivered:

```json
{
  "searchUrl": "https://www.upwork.com/nx/search/talent/?q=copywriting&loc=united-states&revenue=0",
  "maxItems": 1000,
  "skipPreviouslyScraped": true,
  "historyName": "us-copywriters-new"
}
```

A larger pull:

```json
{
  "searchQuery": "python developer",
  "maxItems": 200
}
```

### Pricing

Pay-per-result: you pay only for the freelancer profiles written to your dataset. The price per result depends on your Apify plan:

| Apify plan | Price per result | 1,000 results |
|---|---|---|
| Free | $0.02266 | $22.66 |
| Starter (Bronze) | $0.02078 | $20.78 |
| Scale (Silver) | $0.01888 | $18.88 |
| Business (Gold) | $0.01699 | $16.99 |
| Enterprise (Platinum) | $0.01529 | $15.29 |
| Enterprise (Diamond) | $0.01359 | $13.59 |

#### Optional extras (from 3 October 2026)

A run now carries the standard Apify start fee, charged once per gigabyte of run memory. The price per freelancer is unchanged.

| Event | Price | Charged when |
|---|---|---|
| `apify-actor-start` | $0.005 per GB of run memory ($0.005 per run at the default 1 GB). Bronze $0.0046, Silver $0.0042, Gold and above $0.0038 per GB | the run starts |

New Apify accounts start with $5 in free credit.

### Free users

Free-plan runs return up to 100 results as a preview. [Upgrade your Apify plan](https://console.apify.com/sign-up?fpr=vmoqkp) to lift that cap.

### Run it

1. [Create a free Apify account with $5 in credit](https://console.apify.com/sign-up?fpr=vmoqkp).
2. Open the [Upwork Freelancers Scraper](https://apify.com/parseforge/upwork-freelancers-scraper?fpr=vmoqkp).
3. Set your inputs and any filters, then click **Start**.
4. Export the results as CSV, Excel, JSON, or XML from the **Dataset** tab.

Run it programmatically through the [Apify API](https://docs.apify.com/api/v2) (`run-sync-get-dataset-items`) or the [ApifyClient](https://docs.apify.com/api/client/js) for JavaScript and Python.

### Use with AI agents (MCP)

Give an AI agent live access to Upwork through the Model Context Protocol. Add the Actor to Claude, Cursor, or any MCP client:

```bash
claude mcp add --transport http apify "https://mcp.apify.com?tools=parseforge/upwork-freelancers-scraper"
```

Then prompt it in plain language to run the scraper and read back the results.

### Troubleshooting

**Why am I getting no results?**

Check that your searchQuery is spelled correctly and is a common term on Upwork. Also, try disabling the Top Rated or location filters, as they may be too restrictive for your chosen keyword. The run's status message says which search came back empty, and a run that ends with a warning instead of rows always names the reason.

**I pasted a freelancer's profile link and got no data.**

`upwork.com/freelancers/~01...` is one person's profile page, not a search. This Actor reads Upwork's talent directory, so paste a talent **search** address (`https://www.upwork.com/nx/search/talent/?q=...`) or type the skill in "Skill or job title keyword". The run says so in its status message rather than failing.

**Why is the actor running slowly?**

The actor respects Upwork's pages to avoid blocks. If you are collecting a very large number of profiles, the run will naturally take longer. Try reducing the maxItems for a faster test.

**Why did the log say some search URL filters were skipped?**

Upwork only offers some filters to signed-in clients, English level (`english`) among them. The actor reads the public search, so it applies every filter the public search supports, skips the rest, and lists the skipped ones in the log.

**Why does an earned amount search take longer?**

Upwork does not filter by earnings for visitors, so the actor reads the matching profiles in order and keeps the ones in your bracket. New freelancers tend to sit deeper in the results. You pay only for the profiles that match; a narrower keyword or location finishes faster.

**Why did a run with "Skip freelancers from earlier runs" return fewer profiles than I asked for?**

The history leaves out everyone earlier runs with the same history name already delivered. Once most matches have been collected, few new ones are left, and Upwork shows at most 10,000 results per search. Broaden the keyword or location, or use a new history name to start over.

**Why are my location filters being ignored?**

Only one location filter can be used at a time. If you set a country, the region and sub-region filters are ignored. The 'US Only' checkbox is also ignored when any other location filter is set.

**Why do some profiles have missing data fields?**

Not all freelancers make their full profile public. When a freelancer hides their earnings, Upwork's search still sends $0, so the actor returns `totalEarnings: null` and `earningsHidden: true` (about 1 in 5 experienced freelancers in our tests). `totalEarnings` is also `null`, with `earningsHidden: false`, when Upwork reports $0 for a freelancer who has jobs but no billed hours, because the search cannot tell an unpaid first job from hidden earnings. `jobSuccessScore` is `null` for freelancers who have no score yet or hide it. Other fields are `null` when Upwork sends nothing for them.

**I am getting an error about the input schema.**

Ensure your maxItems is a whole number between 1 and 1,000,000. Also, verify that any country or region name you entered matches the exact spelling from the dropdown list.

### FAQ

| Question | Answer |
|---|---|
| Can I scrape freelancers by a specific skill? | Yes. The searchQuery input accepts any skill or job title keyword, such as 'python developer', 'web scraping', or 'react'. |
| How do I filter for only US-based freelancers? | Enable the 'US Only' checkbox. This filter is ignored if you also set a region, sub-region, or country. |
| What is the difference between Top Rated and Top Rated Plus? | Top Rated is a badge for proven freelancers. Top Rated Plus is a higher tier for top earners on large contracts. You can filter by either or both. |
| Can I combine location filters? | No. Only one location filter can be active at a time. Choose either a region, a sub-region, or a specific country. |
| Does this actor scrape job postings? | No. This actor scrapes freelancer profiles. A separate ParseForge actor for Upwork job postings is in preparation. For job postings on company career sites and job boards, see the jobs actors under Related actors. |
| How many profiles can I collect in one run? | You can set the maximum from 1 up to 1,000,000 profiles per run using the maxItems input. |
| Can I paste an Upwork search URL? | Yes. Put the address of a talent search from upwork.com in the searchUrl input. Its keyword, location, earned amount, hourly rate, job success, hours billed and badge filters replace the matching fields. |
| How do I find new freelancers with no earnings? | Set Earned amount to 'No earnings yet', or paste a search URL that has `revenue=0`. Upwork reports $0 both for new freelancers and for those who hide their earnings. Freelancers with no work history come back with `totalEarnings: 0`. Profiles with hidden or unknown earnings come back with `totalEarnings: null`, so keep only the rows where `totalEarnings` is 0 if you want strictly new freelancers. |
| How do I avoid duplicates between runs? | Turn on "Skip freelancers from earlier runs" and keep the same history name. The actor saves the ID of every freelancer it delivers in a key-value store in your Apify account and leaves them out of later runs. You are charged only for new profiles. |
| Can every run use the same history name? | Yes, that is how it is meant to be used. Keep the same name on every run and each one skips everyone the earlier runs delivered. Use a different name only when you want a separate list. |
| How do I reset the history? | Use a new history name, or delete the key-value store with that name under Storage in Apify Console. |
| Can I filter by English level? | Not yet. Upwork only offers the English level filter to signed-in clients, so it is skipped and noted in the log. |
| Do I need an Upwork account to use this? | No. The actor reads publicly available search results and does not require a login or API key. |
| What data fields does the actor return? | It returns a flat row of 36 fields for each freelancer, including their freelancer ID, name, title, description, hourly rate, total earnings, job success score, hours and jobs worked, Top Rated status, skills, city, country and timezone, intro video link, and agency. |
| How is the Job Success Score written? | `jobSuccessScore` is Upwork's own 0 to 1 fraction (1 means 100%, 0.97 means 97%), and `jobSuccessPercent` is the same score as the whole percent shown on Upwork. Both are `null` when the freelancer has no score or hides it. |
| Which field should I use as a key? | `freelancerId` (the `~01...` ID). The username in `profileUrl` can change; the ID does not. `personId` is Upwork's numeric ID for the same person, sent as text so no digits are lost. |
| What agency data is included? | `agencyId` (`~01...`), `agencyOrgId` (numeric), `agencyName` and `agencyUrl` for the freelancer's first agency, and an `agencies` list with the ID, name, URL, tagline and logo of each agency they belong to. Freelancers without an agency have these empty. |
| Where is the YouTube video? | In `videoUrl`: the link a freelancer added as their profile's video introduction. It is empty when they have none. Links written inside the description text stay in `description`. |
| Can I export the results to Excel? | Yes. The dataset can be exported in CSV, JSON, Excel, or XML formats directly from Apify. |
| How do I avoid getting blocked? | The actor runs on the Apify platform with built-in proxy rotation to help ensure reliable data collection. |

### Next step

Each row carries the fields that these ParseForge jobs Actors take as input:

- **Salaries for the same skill.** Look up a job title from `title` in [Levels.fyi Salary Scraper](https://apify.com/parseforge/levels-fyi-scraper?fpr=vmoqkp) to compare freelance `hourlyRate` with base, stock and bonus pay at tech companies.
- **Full-time demand for the same skill.** Put a skill from `skills` into `searchQuery` of [Indeed Jobs Scraper](https://apify.com/parseforge/indeed-scraper?fpr=vmoqkp) to set freelance `hourlyRate` against the salary ranges employers post for that skill.
- **Companies hiring that skill in-house.** Put the same skill into `searchTerms` of [Career Site Jobs Scraper](https://apify.com/parseforge/career-site-jobs-scraper?fpr=vmoqkp) to find employers with open roles for it on their own career sites.

### Related actors

Other ParseForge jobs actors:

- [Career Site Jobs Scraper](https://apify.com/parseforge/career-site-jobs-scraper?fpr=vmoqkp): open roles straight from company career sites on 21 ATS platforms, with salary and location.
- [Indeed Jobs Scraper](https://apify.com/parseforge/indeed-scraper?fpr=vmoqkp): Indeed job postings in 62 countries, with full descriptions.
- [Glassdoor Jobs Scraper](https://apify.com/parseforge/glassdoor-jobs-scraper?fpr=vmoqkp): Glassdoor job postings with salary and company rating.
- [FlexJobs Scraper](https://apify.com/parseforge/flexjobs-scraper?fpr=vmoqkp): remote and flexible jobs with salary and schedule.
- [Levels.fyi Salary Scraper](https://apify.com/parseforge/levels-fyi-scraper?fpr=vmoqkp): base, stock and bonus pay by company and role.

A separate ParseForge actor for Upwork job postings is in preparation.

Browse the full [ParseForge collection](https://apify.com/parseforge?fpr=vmoqkp) for more scrapers.

🆘 **Need help?** Email parseforge@protonmail.com with your run ID, your input, and what you expected.

⚠️ **Disclaimer.** This Actor is unofficial and is not affiliated with, endorsed by, or sponsored by Upwork Global Inc. It collects only publicly available data. You are responsible for using the collected data in compliance with the source's terms of service and applicable data-protection laws, including GDPR, CCPA, and PIPL. Do not use it to collect personal data unlawfully.

# Actor input Schema

## `searchUrl` (type: `string`):

Paste the address of a talent search on upwork.com (for example https://www.upwork.com/nx/search/talent/?q=copywriting\&loc=united-states\&revenue=0). Its keyword, location, earned amount, hourly rate, job success, hours billed and badge filters replace the matching fields below. Filters that need an Upwork login, such as English level, are skipped and listed in the log. A single freelancer's profile address (upwork.com/freelancers/~01...) is not a search: the run reports it and uses the keyword below instead.

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

Search keyword for finding freelancers (e.g. 'python developer', 'web scraping', 'react'). Several keywords separated by commas run as separate searches and the results are merged, with each freelancer returned once.

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

How many freelancers to collect per run.

## `skipPreviouslyScraped` (type: `boolean`):

Remember every freelancer this actor delivers and leave them out of later runs, so running the same search again returns only new profiles. You are charged only for the new ones. The history is kept in a key-value store in your Apify account under the name below.

## `historyName` (type: `string`):

Name of the key-value store that holds the history (letters, digits and hyphens). Runs that share a name never return the same freelancer twice, even across different searches. Use a separate name per campaign, or delete the store in Storage to start over.

## `earnings` (type: `string`):

Keep only freelancers in this earnings bracket. 'No earnings yet' finds new freelancers who have not been paid on Upwork. Upwork does not filter by earnings for visitors, so the actor reads the results in order and keeps the matches: narrow searches finish faster.

## `hourlyRateMin` (type: `integer`):

Only freelancers charging at least this hourly rate.

## `hourlyRateMax` (type: `integer`):

Only freelancers charging at most this hourly rate.

## `jobSuccessMin` (type: `integer`):

Only freelancers with at least this Job Success Score, from 0 to 100.

## `hoursMin` (type: `integer`):

Only freelancers who billed at least this many hours on Upwork.

## `topRatedOnly` (type: `boolean`):

Only show Top Rated and Top Rated Plus freelancers

## `topRatedPlusOnly` (type: `boolean`):

Only show Top Rated Plus freelancers

## `risingTalentOnly` (type: `boolean`):

Only show freelancers with the Rising Talent badge

## `usOnly` (type: `boolean`):

Only show freelancers from the United States. Ignored when region, sub-region, or country is set.

## `region` (type: `string`):

Filter by continent. Only one location filter can be used at a time (region, sub-region, or country). Overrides 'US Only'.

## `subRegion` (type: `string`):

Filter by sub-region. Only one location filter can be used at a time (region, sub-region, or country). Overrides 'US Only'.

## `country` (type: `string`):

Filter by specific country. Only one location filter can be used at a time (region, sub-region, or country). Overrides 'US Only'.

## Actor input object example

```json
{
  "searchQuery": "python developer",
  "maxItems": 10,
  "skipPreviouslyScraped": false,
  "historyName": "upwork-freelancers-history",
  "earnings": "",
  "topRatedOnly": false,
  "topRatedPlusOnly": false,
  "risingTalentOnly": false,
  "usOnly": false
}
```

# Actor output Schema

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

Dataset with all scraped freelancer profiles

# 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": "python developer",
    "maxItems": 10,
    "historyName": "upwork-freelancers-history"
};

// Run the Actor and wait for it to finish
const run = await client.actor("parseforge/upwork-freelancers-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": "python developer",
    "maxItems": 10,
    "historyName": "upwork-freelancers-history",
}

# Run the Actor and wait for it to finish
run = client.actor("parseforge/upwork-freelancers-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": "python developer",
  "maxItems": 10,
  "historyName": "upwork-freelancers-history"
}' |
apify call parseforge/upwork-freelancers-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,parseforge/upwork-freelancers-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/GJbLfqBRNEkmR90Zu/builds/La9egS13KGImzLFyw/openapi.json
