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

Extract detailed Upwork jobs together with **client history and competition data**. Search by URL or filters, narrow opportunities using budget, applicants, client quality and more, then run searches repeatedly to discover new jobs.

- **URL**: https://apify.com/hiddensins/upwork-jobs-scraper.md
- **Developed by:** [Mox](https://apify.com/hiddensins) (community)
- **Categories:** Automation, Lead generation, Jobs
- **Stats:** 1 total users, 1 monthly users, 86.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $1.50 / 1,000 results

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/actors/running/actors-in-store.md#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 API & Monitor

| ⚡ **Real-Time** | 🧠 **~10MB RAM** | 🌐 **Integrate to anything** | 💰 **~$2 / 1k results** |
| :--- | :--- | :--- | :--- |

***

**Monitor Upwork in real time, find new opportunities, and get detailed client & competition data.**

![Upwork scraper workflow animation](https://res.cloudinary.com/mvw4c1il/image/upload/upwork_scraper_workflow.gif)

- ⚡ **True Real-Time Data (No Stale DBs)**: We scrape Upwork live on request. Get the newest jobs milliseconds after they are posted, not hours later from a cached database.
- 📉 **Micro-Compute Efficiency**: Built on a highly concurrent architecture consuming just **~10MB of RAM**. You pay almost nothing for Apify compute, making this the most cost-effective real-time scraper on the Store.
- 🛡️ **Zero-Friction Authentication**: Proxies and cookies are handled entirely in-house. Paste a URL and get data. Zero ban risk to your personal Upwork account.
- 🔔 **Instant Job Alerts**: Push matches to Telegram, Discord, Slack, or any custom webhook you choose.

***

### ✨ Why use this Actor?

Stop repeatedly searching Upwork for new jobs.

This Actor lets you monitor Upwork searches and automatically receive only new matching jobs — with detailed information about the job, client, budget, competition, and more

#### 🧠 Stupidly easy to use

- **Prompt with a profile**: Use your own Upwork profile link (or any freelancer's) as a prompt. We extract their skills and find relevant jobs matching their expertise.
- **Paste a search URL**: Reproduce any Upwork search instantly.
- **Apply powerful filters**: Budget ranges, applicant counts, client hire rates, countries, and more—all rendered in the UI below.

#### ⚡ Ultra fast and realtime

Instant job search on request with lower usage. You get data while it's still fresh enough to be the *first* applicant.

![Apify RAM & CPU usage dashboard showing ~10MB and <1% CPU](https://res.cloudinary.com/mvw4c1il/image/upload/v1786562778/Screenshot_2026-08-12_202350.png)

#### 📦 Every possible detail

We don't just scrape titles. We pull the full picture so you can bid with confidence.

| **Job Details** | **Client Analytics** | **Competition Signals** |
| :--- | :--- | :--- |
| Title, Description, ID | Payment method verification | Number of applicants |
| Date posted | Phone verification status | Number invited to interview |
| Payment type (Fixed/Hourly) | Location (Country & City) | Invitations sent |
| Fixed budget amount | Jobs posted & Open jobs | Unanswered invitations |
| Hourly budget (Min/Max) | Hire rate (%) | Number of positions to hire |
| Category & Subcategory | Total spent & Total hires | Number already hired |
| Engagement duration | Active projects | *(All in one clean payload!)* |
| Screening questions | Total hours & Avg rate paid | |
| Attachments | Full work history & previous feedback | |

#### 🔌 Supported Integrations & Webhooks

Push matching jobs instantly to your favorite platform. Available integrations:

- <img src="https://cdn.simpleicons.org/telegram/2CA5E0" width="18" align="absmiddle" /> **Telegram**
- <img src="https://cdn.simpleicons.org/discord/5865F2" width="18" align="absmiddle" /> **Discord**
- <img src="https://upload.wikimedia.org/wikipedia/commons/d/d5/Slack_icon_2019.svg" width="18" align="absmiddle" /> **Slack**
- <img src="https://cdn.simpleicons.org/whatsapp/25D366" width="18" align="absmiddle" /> **WhatsApp**
- 🪝 **Generic Webhook** (push to <img src="https://cdn.simpleicons.org/zapier/FF4A00" width="16" align="absmiddle" /> Zapier, <img src="https://cdn.simpleicons.org/make/000000" width="16" align="absmiddle" /> Make, your custom server, etc.)

#### 🎯 Fetch specific jobs by ID

Have a list of Upwork job IDs? Provide them directly, and we return every single detail for those exact postings—no search needed.

#### 🧠 Smart Incremental State

When you enable `onlyNewJobs`, the Actor automatically saves the latest Job IDs to your Apify Key-Value store. On the next run, it checks this state and only pushes jobs it hasn't seen before. No duplicate alerts, ever.

***

### 💸 Pricing that actually makes sense

**$2 per 1,000 job listing pulls.** You can make hundreds of job pulls for less than a cent.

Avoid the hidden Apify costs for RAM and CPU usage. Our actor is super lightweight and runs on **~10MB of RAM**—so your compute costs are practically zero.

***

### 🆚 Why this one is different

Most scrapers on the market fall into two traps: they are either heavy Node.js browser automations that drain your Apify compute credits, or they rely on pre-indexed databases that feed you stale data. We built a third option.

| Feature | ⚡ Upwork Jobs API (This Actor) | Traditional Node.js Scrapers | Cached Database Scrapers |
| :--- | :--- | :--- | :--- |
| **Architecture** | **Lightweight Engine** | Heavy Puppeteer / Playwright | Database querying |
| **Data Freshness** | **True Real-Time (Live)** | Live (but slow to boot) | Stale (Hours to days old) |
| **RAM Footprint** | **~10MB** (Costs pennies) | 500MB – 1GB+ (Expensive) | Varies |
| **Native Webhooks** | **Yes** (Discord, Slack, Telegram) | No (Requires Zapier) | No (Requires Zapier) |
| **Anti-Bot / Proxies** | **100% Handled In-House** | Often requires your cookies | Not applicable |
| **Avg. Cost per 1k** | **~$2.00** | ~$3.00 – $4.00 | ~$3.50 – $4.50 |
-----------------------------------------------------------------------

### 🚀 Quickstart

Here are **3 ways** to run this Actor, depending on what you need.

#### Example 1: The "Paste & Go" (Search URL)

Just paste your Upwork search URL. We handle the rest.

```json
{
  "searchUrl": "https://www.upwork.com/nx/search/jobs/?q=python+fastapi",
  "maxItems": 50
}
```

#### Example 2: Profile-Powered Search

Paste a freelancer profile link. We analyze their skills and title to find matching jobs automatically.

```json
{
  "freelancerProfileUrl": "https://www.upwork.com/freelancers/~01234XXXXXXXXXX",
  "paymentType": "HOURLY",
  "minHourlyRate": 50,
  "maxApplicants": 10,
  "paymentVerified": true,
  "maxItems": 25
} 

```

#### Example 3: The "Monitor & Push" (Webhook + Dedupe)

Run this every 5 minutes. We'll only return new jobs and push them directly to your custom endpoint.

```json
{
  "searchUrl": "https://www.upwork.com/nx/search/jobs/?q=ai+developer",
  "onlyNewJobs": true,
    "telegramBotToken": "12345:XXXXXXXXXXXXXXXXXXX",
  "telegramChatId": "1234567"
  "minClientTotalSpent": 10000,
  "minHireRate": 80,
  "maxItems": 10
}
```

### 📤 Output Example

<details>
<summary>Click to view JSON data</summary>

```json
  {
    "jobId": "~022087591245131988229",
    "jobTitle": "Automated Clay.com Expert Needed: High-Volume Meta Ads B2B Scraping (MedSpas - 10,000 Leads/Mo)",
    "datePosted": "2026-08-12T17:25:13.438Z",
    "paymentType": "FIXED",
    "budgetAmount": 1000,
    "hourlyBudgetMinimum": null,
    "hourlyBudgetMaximum": null,
    "jobDescription": "We are scaling an aggressive B2B Voice AI engine and need an expert Clay & Data Scraping Specialist to build and run a high-volume pipeline generating 5,000 verified leads ev...",
    "categoryGroup": "Sales & Marketing",
    "subCategory": "Lead Generation & Telemarketing",
    "engagementDuration": "3 to 6 months",
    "questions": [],
    "attachments": [],
    "clientActivity.lastBuyerActivity": "2026-08-12T18:45:56.971Z",
    "clientActivity.totalApplicants": 16,
    "clientActivity.totalHired": 0,
    "clientActivity.totalInvitedToInterview": 11,
    "clientActivity.unansweredInvites": 15,
    "clientActivity.invitationsSent": 30,
    "clientActivity.numberOfPositionsToHire": 1,
    "buyer.paymentMethodVerified": true,
    "buyer.phoneVerificationStatus": "VERIFIED",
    "buyer.locationCountry": "Israel",
    "buyer.locationCity": "Qiryat Ono",
    "buyer.jobsPosted": 4,
    "buyer.openJobs": 2,
    "buyer.hireRate": 50,
    "buyer.totalSpent": 1090.58,
    "buyer.totalHires": 3,
    "buyer.activeProjects": 1,
    "buyer.averageHourlyRatePaid": 24.998056837503036,
    "buyer.totalHours": 41.17,
    "buyer.industry": null,
    "buyer.workHistory": [
      {
        "status": "ACTIVE",
        "startDate": "2026-08-06T12:18:31.399Z",
        "endDate": null,
        "totalCharge": 5,
        "totalHours": 0,
        "jobInfo": {
          "title": "High-Intent B2B Lead Gen (MedSpa Niche): Clay.com & Meta Ads Data Sourcing Expert Needed",
          "type": "FIXED",
          "ciphertext": "~022085305434284023094"
        },
        "contractorInfo": {
          "contractorName": "Shoaib I.",
          "ciphertext": "~01042dd120221d9906"
        },
        "rate": null,
        "feedback": null,
        "feedbackToClient": null
      },
      {
        "status": "CLOSED",
        "startDate": "2024-05-18T21:22:07.425Z",
        "endDate": "2025-03-21T14:36:36.141Z",
        "totalCharge": 1085.58,
        "totalHours": 41.166667,
        "jobInfo": {
          "title": "A programmer is needed",
          "type": "HOURLY",
          "ciphertext": "~01a1b12b16f0b81ad1"
        },
        "contractorInfo": {
          "contractorName": "Inderjeet S.",
          "ciphertext": "~01063966e1b142416b"
        },
        "rate": {
          "amount": 26.25
        },
        "feedback": null,
        "feedbackToClient": {
          "score": 5,
          "comment": ""
        }
      }
    ]
  }
```

</details>

### 🆘 Support & Custom Integrations

Upwork updates their platform frequently, and we update this engine just as fast.

Found a bug? Open an Issue in the Apify Console.

Need a custom integration? We can easily add custom webhook formats, new data fields, or private instances. Reach out via the Apify Issues tab!

# Actor input Schema

## `freelancerProfileUrl` (type: `string`):

Optional. Paste an Upwork freelancer profile URL. This is the easiest way to get relevant jobs to a profile.

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

Optional. Paste an Upwork search URL. This is the easiest way to reproduce an existing Upwork search.

## `keywords` (type: `array`):

Only return jobs containing at least one of these keywords in the job title or description.

## `excludeKeywords` (type: `array`):

Exclude jobs containing any of these keywords in the title or description.

## `category` (type: `string`):

Only return jobs from the selected Upwork category. You can also enter a custom category.

## `subCategory` (type: `string`):

Optional. Narrow results to a specific Upwork subcategory.

## `paymentType` (type: `string`):

Choose which type of jobs to include.

## `minFixedBudget` (type: `integer`):

Only return fixed-price jobs with a budget of at least this amount.

## `maxFixedBudget` (type: `integer`):

Only return fixed-price jobs with a budget up to this amount.

## `minHourlyRate` (type: `integer`):

Only return hourly jobs where the advertised rate reaches at least this amount.

## `maxHourlyRate` (type: `integer`):

Only return hourly jobs where the advertised rate does not exceed this amount.

## `engagementDuration` (type: `array`):

Only return jobs matching one or more expected engagement durations.

## `postedWithinHours` (type: `integer`):

Only return jobs posted within this many hours.

## `minPositions` (type: `integer`):

Only return jobs where the client is hiring at least this many people.

## `maxPositions` (type: `integer`):

Only return jobs where the client is hiring no more than this many people.

## `minApplicants` (type: `integer`):

Only return jobs with at least this many applicants.

## `maxApplicants` (type: `integer`):

Only return jobs with no more than this many applicants.

## `minInvitationsSent` (type: `integer`):

Only return jobs where the client has sent at least this many invitations.

## `maxInvitationsSent` (type: `integer`):

Only return jobs where the client has sent no more than this many invitations.

## `minInvitedToInterview` (type: `integer`):

Only return jobs where at least this many applicants have been invited to interview.

## `maxInvitedToInterview` (type: `integer`):

Avoid jobs where too many applicants have already been invited to interview.

## `maxUnansweredInvites` (type: `integer`):

Only return jobs with no more than this number of unanswered invitations.

## `paymentVerified` (type: `boolean`):

Only return jobs from clients with a verified payment method.

## `phoneVerified` (type: `boolean`):

Only return jobs from clients with a verified phone number.

## `minHireRate` (type: `integer`):

Only return jobs from clients with a historical hire rate of at least this percentage.

## `minClientTotalSpent` (type: `integer`):

Only return jobs from clients who have spent at least this amount on Upwork.

## `minClientHires` (type: `integer`):

Only return jobs from clients who have previously hired at least this many freelancers.

## `minClientJobsPosted` (type: `integer`):

Only return jobs from clients who have posted at least this many jobs.

## `minClientOpenJobs` (type: `integer`):

Only return jobs from clients who currently have at least this many open jobs.

## `minClientActiveProjects` (type: `integer`):

Only return jobs from clients who currently have at least this many active projects.

## `minClientTotalHours` (type: `integer`):

Only return jobs from clients who have previously hired freelancers for at least this many hours.

## `minAverageHourlyRatePaid` (type: `integer`):

Only return jobs from clients whose historical average hourly rate paid is at least this amount.

## `clientCountries` (type: `array`):

Only return jobs from clients located in the selected countries. You can also enter custom countries.

## `excludeClientCountries` (type: `array`):

Exclude jobs from clients located in the selected countries.

## `clientCities` (type: `array`):

Only return jobs from clients located in these cities.

## `hasQuestions` (type: `boolean`):

Only return jobs that contain one or more screening questions.

## `hasAttachments` (type: `boolean`):

Only return jobs that contain one or more attachments.

## `clientIndustry` (type: `string`):

Only return jobs from clients in the selected industry. Availability depends on Upwork providing industry information.

## `onlyNewJobs` (type: `boolean`):

When running the same search repeatedly, return only jobs that have not been returned by a previous run.

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

Maximum number of matching jobs to return.

## `telegramBotToken` (type: `string`):

Your Telegram Bot Token.

## `telegramChatId` (type: `string`):

Your Telegram Chat or Channel ID.

## `discordWebhookUrl` (type: `string`):

Your Discord Webhook URL.

## `slackWebhookUrl` (type: `string`):

Your Slack Incoming Webhook URL.

## `whatsappPhoneNumberId` (type: `string`):

Your WhatsApp Phone Number ID.

## `whatsappAccessToken` (type: `string`):

Your WhatsApp Access Token.

## `whatsappRecipient` (type: `string`):

The WhatsApp Recipient phone number.

## `genericWebhookUrl` (type: `string`):

A generic webhook URL to dispatch scraped jobs to.

## `webhookHeaders` (type: `object`):

Optional HTTP headers to send with the generic webhook. Specify as JSON object.

## Actor input object example

```json
{
  "freelancerProfileUrl": "https://www.upwork.com/freelancers/~010bbabXXXXXXX",
  "searchUrl": "https://www.upwork.com/nx/search/jobs/?q=python",
  "paymentType": "ANY",
  "postedWithinHours": 24,
  "paymentVerified": false,
  "phoneVerified": false,
  "onlyNewJobs": false,
  "maxItems": 100
}
```

# 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 = {
    "freelancerProfileUrl": "https://www.upwork.com/freelancers/~010bbabXXXXXXX",
    "searchUrl": "https://www.upwork.com/nx/search/jobs/?q=python",
    "postedWithinHours": 24
};

// Run the Actor and wait for it to finish
const run = await client.actor("hiddensins/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 = {
    "freelancerProfileUrl": "https://www.upwork.com/freelancers/~010bbabXXXXXXX",
    "searchUrl": "https://www.upwork.com/nx/search/jobs/?q=python",
    "postedWithinHours": 24,
}

# Run the Actor and wait for it to finish
run = client.actor("hiddensins/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 '{
  "freelancerProfileUrl": "https://www.upwork.com/freelancers/~010bbabXXXXXXX",
  "searchUrl": "https://www.upwork.com/nx/search/jobs/?q=python",
  "postedWithinHours": 24
}' |
apify call hiddensins/upwork-jobs-scraper --silent --output-dataset

```

## MCP server setup

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