# Upwork Recent Jobs (`mtahreemalam/upwork-recent-jobs`) Actor

Extract up to 1,000 recent Upwork jobs, filter by publication date, and export results as CSV or JSON.

- **URL**: https://apify.com/mtahreemalam/upwork-recent-jobs.md
- **Developed by:** [Muhammed Tahreem Alam](https://apify.com/mtahreemalam) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 69.2% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.50 / 1,000 saved 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/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

## Upwork Recent Jobs

Collect bounded public Upwork job batches, filter by publication date and remove duplicate IDs.

### Input

```
{"query": "", "maxJobs": 1000, "maxAgeHours": 24, "useResidentialProxy": true}
```

query is optional, at most256 characters; blank covers public job categories.
maxJobs accepts1-1000, default1000. maxAgeHours accepts1-168, default24.
The lower publication cutoff is fixed at run start.

### Results

Use Apify Console or its API. Results go into the default dataset, downloadable as JSON or CSV. The OUTPUT key-value record holds counts, exclusions, timestamps, request receipts and the stopping reason.

Each row contains ID, title, description, publication/creation/sourcing dates, job type, skills, hourly/fixed budget fields and collection time. Source-empty fields stay empty. Results sort by publication date.

COMPLETE_TARGET means the requested number was collected, not complete period coverage.
PARTIAL means the search, page/time or spending limit ended before the target. A charge_limit stopping reason means the maximum run cost could not cover more jobs; counts describe saved results.
EMPTY means a valid search ended without qualifying rows.
BLOCKED or FAILED fails the run while preserving earlier usable results and summary.
Invalid inputs fail before contacting Upwork.

Newest-first API ordering mixes old publications with recent sourcing dates, so this Actor checks publishTime directly. Offset pagination can move; deduplication does not prove no records were skipped.

Limits:40 pages of50 rows, at most41 Upwork requests,180-second collection budget,15-second request timeout,2 seconds between request starts. No retries, redirects, login or automatic IP fallback. Monotonic request intervals are recorded. No automatic polling or notifications.

### Release and costs

Early release. Verified privately on Apify on25October2026: a10-job smoke test and a1,000-job publication-qualified run both passed. The bulk run took about43seconds; sustained reliability remains untested. No availability, completeness or instant-detection guarantee. See the Store pricing tab for the currently effective model and any scheduled change. Approved paid pricing is $0.50 per1,000 saved qualified unique jobs, plus $0.00005 per start at up to1GB RAM. With that pay-per-event pricing active, compute, storage and residential proxy usage are included; there are no paid data add-ons. Until activation, the previous pay-per-usage model remains in effect. Creator payout setup is required before activation. No source-code publication.

Residential proxy is enabled by default because the direct Apify test returned403. Under pay-per-event pricing, residential traffic is included in the listed price. Under pay-per-usage pricing, Apify bills proxy traffic at your account rate in addition to compute/storage. Set useResidentialProxy to false to try direct access. One proxy session is used for the whole guest-token/search sequence; no automatic session/IP retries. The provider may still replace an unavailable or expired residential IP.

curl_cffi makes HTTP requests. REA supported earlier discovery and response inspection; it is not a runtime dependency. Tokens never appear in output or logs.

### Development

Canonical source is the Upwork Recent Jobs project on Xeon E:.
Python3.12; hash-locked dependencies in requirements.txt.
Run checks: python -B -m unittest discover -s tests -v
Run Actor: python -m upwork_actor
.venv, artifacts, storage and credentials are ignored.
See docs/plan.md for decisions, approvals and deployment state.

### Example result fields

Description and other timestamps are also present in the dataset. Source-empty fields remain empty. The following fields come from the private acceptance run:

```
{"id": "2114240781485364114", "title": "Vietnam-Based B2B Sales Representatives for AI Services | Pay per Sales Meeting", "publishTime": "2026-10-25T06:21:39.808Z", "jobType": "FIXED", "skills": ["Sales Development", "Business Development", "Sales Strategy"], "hourlyBudgetMin": null, "hourlyBudgetMax": null, "fixedPriceAmount": "12.75", "currency": null}
```

# Actor input Schema

## `query` (type: `string`):

Optional keyword. Blank covers public job categories.

## `maxJobs` (type: `integer`):

Maximum number of unique date-qualified jobs. Bounded searches may return fewer.

## `maxAgeHours` (type: `integer`):

Publication-age window in hours; the cutoff is calculated at run start.

## `useResidentialProxy` (type: `boolean`):

Recommended on Apify: direct access was blocked. Traffic is included when pay-per-event pricing is active; otherwise platform/proxy usage charges apply. Disable only to try direct access. One session is used; no automatic IP retries.

## Actor input object example

```json
{
  "query": "",
  "maxJobs": 1000,
  "maxAgeHours": 24,
  "useResidentialProxy": true
}
```

# Actor output Schema

## `jobsJson` (type: `string`):

No description

## `jobsCsv` (type: `string`):

No description

## `summary` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("mtahreemalam/upwork-recent-jobs").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("mtahreemalam/upwork-recent-jobs").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 '{}' |
apify call mtahreemalam/upwork-recent-jobs --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,mtahreemalam/upwork-recent-jobs"
        }
    }
}
```

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/C1quyjeYs6If1VePC/builds/nD50vagv6M8JcE4pD/openapi.json
