# Upwork Jobs Scraper (`piotrv1001/upwork-jobs-scraper`) Actor

The Upwork Jobs Scraper extracts job listings from Upwork, capturing titles, descriptions, hourly and fixed budgets, skills, experience level and duration, plus optional client spend, hire rate, rating and applicant counts — ideal for freelance lead generation and rate benchmarking.

- **URL**: https://apify.com/piotrv1001/upwork-jobs-scraper.md
- **Developed by:** [FalconScrape](https://apify.com/piotrv1001) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 jobs

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/platform/actors/running/actors-in-store#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

### 🚀 Upwork Jobs Scraper

Easily extract job listings from Upwork. The **Upwork Jobs Scraper** turns the Upwork job marketplace into clean, structured data you can use for freelance lead generation, rate benchmarking, and hiring-market research — no login and no manual copy-pasting required.

Search by keyword, or leave the query empty to browse everything currently open. Every job comes back with its budget, required skills, experience level, project duration and posting date. Flip one switch and each job is enriched with client intelligence: total spend, hire rate, rating, industry, location and how many freelancers have already applied.

### ✨ Features

- 💼 **Complete Job Data**: Title, full description, hourly rate range or fixed budget, experience level, project duration, expected workload, required skills and posting date.
- 🔍 **Keyword Search**: Pass any number of search terms — `python developer`, `shopify`, `logo design` — and get every matching open job.
- 🌍 **Browse Everything**: Leave the search empty to sweep the whole public job feed instead of a single niche.
- 🏢 **Client Intelligence** (optional): Total amount spent, jobs posted, hire rate, average rating, hours billed, company industry and size, city and timezone.
- 📈 **Competition Signals** (optional): Number of applicants, freelancers already hired, interview invitations sent and the client's last activity — so you can spot fresh, low-competition jobs before everyone else.
- 💸 **Pay Only For What You Use**: Cheap per-listing pricing, with the expensive client lookups billed separately and switched off by default.

### 🛠️ How It Works

1. **Enter Search Queries** – Add one or more keywords, or leave the field empty to browse all open jobs.
2. **Set a Limit** – Choose how many jobs you want (defaults to 50).
3. **Optionally Enable Client Details** – Turn on *Scrape client details* for client spend, ratings and applicant counts.
4. **Run the Scraper** – Start the run and download your results as JSON, CSV, Excel or HTML.

### 📥 Input

| Field              | Type    | Default                | Description                                                         |
| ------------------ | ------- | ---------------------- | ------------------------------------------------------------------- |
| `searchQueries`    | array   | `["python developer"]` | Keywords to search for. Leave empty to browse all open jobs.        |
| `maxItems`         | integer | `50`                   | Maximum number of jobs to scrape across all queries.                |
| `scrapeJobDetails` | boolean | `false`                | Also collect client intelligence and applicant counts for each job. |

```json
{
    "searchQueries": ["python developer", "data engineer"],
    "maxItems": 100,
    "scrapeJobDetails": false
}
```

### 📊 Sample Output Data

The scraper provides structured JSON output. Example of a job listing:

```json
[
    {
        "id": "2081794040827272124",
        "ciphertext": "~022081794040827272124",
        "title": "Data Tracking and Reporting System - Python Dashboard Developer needed",
        "description": "I work as a project manager for a small group - part time. This is a group of Contract Specialists that complete a number of contract actions on a daily basis...",
        "jobType": "Hourly",
        "hourlyRateMin": 10,
        "hourlyRateMax": 15,
        "fixedBudget": null,
        "currency": "USD",
        "experienceLevel": "Intermediate",
        "duration": "Less than 1 month",
        "workload": "Part time",
        "skills": ["Python", "Database", "API", "Web Design", "Django"],
        "isPremium": false,
        "publishedAt": "2026-07-27T20:30:56.280Z",
        "createdAt": "2026-07-27T17:29:12.373Z",
        "renewedAt": null,
        "searchQuery": "python developer",
        "url": "https://www.upwork.com/jobs/Data-Tracking-and-Reporting-System-Python-Dashboard-Developer-needed_~022081794040827272124/"
    }
]
```

With **Scrape client details** enabled, each job additionally carries:

```json
{
    "clientCountry": "United States",
    "clientCity": "Hackettstown",
    "clientTimezone": "America/Indiana/Knox (UTC-05:00)",
    "clientPaymentVerified": true,
    "clientTotalSpent": 57.24,
    "clientTotalJobsPosted": 1,
    "clientActiveJobs": 1,
    "clientTotalHires": 1,
    "clientTotalHours": 2,
    "clientRating": 0,
    "clientTotalReviews": 0,
    "clientIndustry": "Supply Chain & Logistics",
    "clientCompanySize": 1,
    "totalApplicants": 16,
    "totalHired": 1,
    "totalInterviewing": 0,
    "invitationsSent": 2,
    "lastClientActivity": "2026-08-04T22:37:51.255Z",
    "occupation": "Coding Tutoring"
}
```

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

### 📋 Output Fields

| Field                                                  | Description                                 |
| ------------------------------------------------------ | ------------------------------------------- |
| `id` / `ciphertext`                                    | Unique Upwork job identifiers               |
| `title`                                                | Job title                                   |
| `description`                                          | Full job description                        |
| `url`                                                  | Direct link to the job on Upwork            |
| `jobType`                                              | `Hourly` or `Fixed price`                   |
| `hourlyRateMin` / `hourlyRateMax`                      | Client's hourly budget range                |
| `fixedBudget`                                          | Fixed-price budget                          |
| `experienceLevel`                                      | Entry level, Intermediate or Expert         |
| `duration`                                             | Expected project length                     |
| `workload`                                             | Part time, Full time, As needed or Not sure |
| `skills`                                               | Skills requested on the posting             |
| `publishedAt` / `createdAt` / `renewedAt`              | Posting timestamps                          |
| `clientTotalSpent`                                     | Lifetime client spend on Upwork \*           |
| `clientTotalJobsPosted` / `clientTotalHires`           | Client hiring history \*                     |
| `clientRating` / `clientTotalReviews`                  | Client feedback score \*                     |
| `clientCountry` / `clientCity` / `clientTimezone`      | Client location \*                           |
| `clientIndustry` / `clientCompanySize`                 | Client company profile \*                    |
| `totalApplicants` / `totalHired` / `totalInterviewing` | Current competition on the job \*            |
| `lastClientActivity`                                   | When the client was last active \*           |

\* Requires **Scrape client details** to be enabled.

### 💰 How Much Does It Cost to Scrape Upwork?

This Actor uses pay-per-event pricing, so you pay for results rather than for runtime.

| Event                   | Price          |
| ----------------------- | -------------- |
| Actor start             | $0.005 per run |
| Job listing             | $0.002 per job |
| Job with client details | $0.022 per job |

**Examples:**

- 1,000 job listings → **$2.01**
- 100 jobs with full client details → **$2.21**
- 5,000 job listings (daily market sweep) → **$10.01**

Jobs are billed at the client-details rate only when those details were actually retrieved — if a lookup fails, that job is billed as a plain listing.

### 💡 Tips

- **Start without client details.** The listing data alone already contains budgets, skills and experience level, and is roughly 10× cheaper per job.
- **Use several narrow queries** instead of one broad one. Upwork returns more distinct jobs across `python`, `django` and `fastapi` than across `python` alone.
- **Schedule a daily run** with a modest `maxItems` to build your own historical rate database over time — Apify's scheduler and integrations (Slack, Google Sheets, webhooks, API) make this a one-time setup.
- **Deduplicate on `id`** when combining results from multiple queries; the same job can match more than one keyword.

### ❓ FAQ

**Do I need an Upwork account?**
No. The Actor only reads publicly visible job postings.

**How fresh are the results?**
Results reflect what Upwork shows to logged-out visitors at the time of the run. Run the Actor on a schedule to keep your dataset current.

**Why did I get fewer jobs than my `maxItems` limit?**
Upwork's public job feed is finite, and narrow keywords may simply have fewer open postings. The log reports how many jobs were available for each query.

**Is scraping Upwork legal?**
This Actor collects only publicly accessible information and does not gather personal data. You are responsible for how you use the extracted data, including compliance with Upwork's terms and applicable laws such as GDPR. If in doubt, seek legal advice.

**Something isn't working.**
Report it on the Issues tab and it will be looked into. Custom solutions and extra fields can be arranged on request.

Start finding better freelance work and better clients with **Upwork Jobs Scraper** today! 🚀

# Actor input Schema

## `searchQueries` (type: `array`):

Keywords to search Upwork jobs for, one per line. Leave empty to browse all currently open jobs.

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

Maximum number of job listings to scrape across all search queries.

## `scrapeJobDetails` (type: `boolean`):

Also open each job to collect client intelligence: total spent, hire rate, rating, location, industry, number of applicants and interview activity. Much slower and billed at a higher rate per job.

## Actor input object example

```json
{
  "searchQueries": [
    "python developer"
  ],
  "maxItems": 50,
  "scrapeJobDetails": false
}
```

# Actor output Schema

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

No description

# 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 = {
    "searchQueries": [
        "python developer"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("piotrv1001/upwork-jobs-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 = { "searchQueries": ["python developer"] }

# Run the Actor and wait for it to finish
run = client.actor("piotrv1001/upwork-jobs-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 '{
  "searchQueries": [
    "python developer"
  ]
}' |
apify call piotrv1001/upwork-jobs-scraper --silent --output-dataset

```

## MCP server setup

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