# Wuzzuf Jobs Scraper \[💰$0.85] - Applicant Counts & Salaries (`corvuslab/wuzzuf-jobs-scraper`) Actor

Scrape Wuzzuf.net jobs in Egypt, Saudi Arabia, UAE and 12 more countries: title, salary, experience, skills, education, applicant counts (applied, viewed, shortlisted, rejected) and company website, LinkedIn & industry. Filters, incremental monitoring and Telegram/Slack alerts.

- **URL**: https://apify.com/corvuslab/wuzzuf-jobs-scraper.md
- **Developed by:** [Corvuslab](https://apify.com/corvuslab) (community)
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.85 / 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?

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

### What does Wuzzuf Jobs Scraper do?

Wuzzuf Jobs Scraper pulls job listings from **[Wuzzuf.net](https://wuzzuf.net)**, Egypt's largest job board, and returns **70 structured fields per job**: title, salary, experience range, skills, education, the full description and requirements, and the hiring company's profile. On top of that it returns two kinds of data most job scrapers lack: **applicant demand** (how many people applied, and how many applications the employer viewed, shortlisted and rejected) and **company intelligence** (website, LinkedIn, Facebook, industry, founding year).

Give it search terms, countries, cities or districts, or paste Wuzzuf URLs. Every matching job comes back as a clean record you can export to JSON, CSV or Excel, pull from the API, or hand to an AI agent. With no input at all, it returns the 25 newest jobs on the board. No login, cookies or proxy needed.

> New to Apify? Sign up free and use the included monthly platform credit to try this Actor. No credit card needed.

***

### What data can you extract from Wuzzuf?

Every record carries **70 fields** (78 with incremental change tracking), grouped like this:

| Group | What you get |
|---|---|
| **Job** | `title`, `url`, `jobTypes`, `employmentType`, `workplaceArrangement`, `careerLevel`, `categories`, `skills`, `vacancies`, `postedAt`, `expiresAt`, `isFeatured`, `status`, `applyType`, `applyUrl` |
| **Salary & experience** | `salaryText`, `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod`, `salaryHidden`, `salaryNotes`, `experienceYearsMin`, `experienceYearsMax`, `experienceText` |
| **Applicant demand** | `applicantCount`, `applicantVolumeLabel`, `applicationsViewed`, `applicationsShortlisted`, `applicationsRejected`, `applicationsNotSelected`, `jobViews`, `screeningQuestions` |
| **Candidate preferences** | `educationLevel`, `genderPreference` |
| **Company** | `company`, `companyId`, `companyConfidential`, `companyUrl`, `companyWebsite`, `companyLinkedin`, `companyFacebook`, `companySocialProfiles`, `companyIndustry`, `companyIndustries`, `companyDescription`, `companyLogo`, `companyEstablishedYear`, `companyIsVerified`, `companyHiringFor`, `companySpecialties`, `companyPerks` |
| **Location** | `location`, `area` (district), `city`, `country`, `countryCode`, `latitude`, `longitude` |
| **Text** | `description` and `requirements` as plain text, HTML and/or Markdown |
| **Run info** | `searchKeyword`, `source`, `scrapedAt`, `contentHash`, plus `changeType`, `firstSeenAt`, `lastSeenAt`, `previousSeenAt`, `expiredAt` and repost fields in incremental mode |

***

### Key features

- 📊 **Applicant demand on 99.5% of jobs**: applicants, applications viewed / shortlisted / rejected / not selected, page views, screening-question count and a demand label. Spot low-competition openings before you apply or pitch.
- 🏢 **Company intelligence for lead lists**: the employer's website, socials, industry, founding year, description, logo, specialties and perks arrive with every job.
- 🎚️ **The site's own filters**: job type, workplace (on-site / hybrid / remote), career level, all 37 Wuzzuf job categories, posted within, years of experience, 15 countries, and any city or district.
- 💰 **Screens that don't bill**: *Only jobs with a published salary*, *Minimum monthly salary* and *Skip confidential employers* drop jobs before they're charged.
- 🧾 **Numbers, not just text**: salary min / max / currency / period and min–max years of experience as numbers, ready to sort and chart.
- ♻️ **Incremental monitoring**: scheduled runs emit only new, changed and expired jobs. Unchanged jobs cost nothing.
- 🔔 **Alerts**: Telegram, Slack, Discord or any webhook (n8n, Make, Zapier).
- 🤖 **AI-ready output**: compact and drop-empty modes keep payloads small for LLMs and MCP clients.

***

### 🚀 How to scrape Wuzzuf

1. Enter one or more **search terms** (e.g. `accountant`). Then pick countries, cities or filters, or paste a Wuzzuf URL.
2. Set **Max results** (0 = every matching job).
3. Optionally turn on a salary screen, **incremental mode** and a notification channel.
4. Click **Start**, then download the results as JSON, CSV or Excel, or pull them from the API.

#### Quick-start example input

```json
{
  "searchTerms": ["accountant"],
  "locations": ["Cairo", "Giza"],
  "careerLevels": ["experienced"],
  "postedWithin": "week",
  "maxResults": 100
}
```

This returns up to 100 experienced-level accountant jobs posted in Cairo or Giza in the past week. Sort by `applicantCount` to go after the openings with the least competition first.

***

### Input

Configure it in the visual editor or pass JSON via the API. The main inputs:

| Field | Type | What it does |
|---|---|---|
| `searchTerms` | array | Job titles, skills or keywords. Each term runs as its own search; results are merged and de-duplicated. Empty = all jobs. |
| `countries` | array | Egypt, Saudi Arabia, United Arab Emirates, Qatar, Kuwait, Oman, Bahrain, Jordan, Lebanon, Iraq, Libya, Algeria, United States, United Kingdom, Germany. |
| `locations` | array | Cities (`"Cairo"`, `"Alexandria"`, `"Riyadh"`) or districts (`"New Cairo"`, `"Nasr City"`, `"Maadi"`). `"City, Country"` works too. |
| `startUrls` | array | Wuzzuf search URLs (filters included), country pages (`wuzzuf.net/jobs/egypt`) or single job URLs (`wuzzuf.net/jobs/p/…`). When set, these replace the search form. |
| `maxResults` | integer | Total jobs to return across all terms and places (default 25; 0 = all). |
| `jobTypes` / `workplace` / `careerLevels` | array | `full_time`, `part_time`, `freelance_project`, `internship`, `shift_based`, `volunteering` / `on_site`, `hybrid`, `remote` / `student`, `entry_level`, `experienced`, `manager`, `senior_management`. |
| `categories` | array | Any of Wuzzuf's 37 job categories (IT/Software Development, Accounting/Finance, Sales/Retail, …). |
| `postedWithin` | enum | `any`, `24h`, `week`, `month`. |
| `yearsOfExperience` | integer | Only jobs whose required range includes this number. Jobs with no stated range are kept. |
| `onlyWithSalary` / `minSalary` / `excludeConfidential` | boolean / integer / boolean | The free screens. `minSalary` is monthly, top of the range, in the job's own currency. |
| `includeApplicantInsights` / `includeCompanyProfile` | boolean | Applicant and company field groups (both on by default). |
| `descriptionFormat` / `descriptionMaxLength` | enum / integer | `all`, `text`, `html` or `markdown`, and an optional character limit. |
| `compact` / `excludeEmptyFields` | boolean | Core fields only / drop empty fields. |

Several values inside one filter widen the search (OR); different filters narrow it (AND). Incremental and notification inputs are covered in their own sections below. Under **Advanced** you'll find an optional proxy setting (not needed), request retries, and whether unreadable start URLs are skipped or fail the run.

#### More example inputs

Remote and hybrid IT jobs in Egypt paying at least 30,000 EGP a month:

```json
{
  "countries": ["Egypt"],
  "categories": ["IT/Software Development"],
  "workplace": ["remote", "hybrid"],
  "minSalary": 30000,
  "maxResults": 0
}
```

A Gulf hiring lead list with confidential employers skipped:

```json
{
  "countries": ["Saudi Arabia", "United Arab Emirates", "Kuwait"],
  "excludeConfidential": true,
  "maxResults": 0
}
```

***

### Output

Each dataset item is one Wuzzuf job. A real record (trimmed):

```json
{
  "id": "1706f44c-442f-4c5a-9daf-3e63575665d3",
  "title": "(German / Spanish / French / English) Customer Service & Outbound Sales Specialist",
  "url": "https://wuzzuf.net/jobs/p/7wuxftdegdtk-german-spanish-french-english-customer-service-outbound-sales-specialist-riseup-endemag-for-administrative-skills-development-cairo-egypt",
  "company": "RISEUP (Endemag for Administrative Skills Development)",
  "location": "Maadi, Cairo, Egypt",
  "employmentType": "Full Time",
  "workplaceArrangement": "On-site",
  "careerLevel": "Experienced",
  "categories": ["Customer Service/Support", "Quality", "Sales/Retail"],
  "skills": ["Sales", "Customer Service", "English", "French", "German", "Spanish Teaching"],
  "experienceYearsMin": 3,
  "experienceYearsMax": 7,
  "salaryText": "24,000 - 48,000 EGP Per Month",
  "salaryMin": 24000.0,
  "salaryMax": 48000.0,
  "salaryCurrency": "EGP",
  "salaryPeriod": "month",
  "vacancies": 33,
  "educationLevel": "Bachelor's Degree",
  "postedAt": "2026-10-14T09:37:45+00:00",
  "applicantCount": 5,
  "applicantVolumeLabel": "Low",
  "applicationsViewed": 4,
  "applicationsRejected": 1,
  "screeningQuestions": 3,
  "description": "Job Description\nWe’re hiring Customer Service Representatives & Outbound Sales Representatives who speak English or French or German or Spanish…",
  "companyWebsite": "https://www.riseupgrp.com",
  "companyLinkedin": "https://www.linkedin.com/company/riseupgrp/",
  "companyIndustry": "Human Resources",
  "companyEstablishedYear": 2017,
  "scrapedAt": "2026-10-14T15:28:11.452488+00:00"
}
```

Every field is present on every record, with `null` where Wuzzuf has no value. Times are in UTC. **Compact mode** keeps only the core fields, and **`excludeEmptyFields`** drops empty ones. The Output tab has two ready-made views: **Overview** (one row per job) and **Companies hiring** (employer, industry, website, LinkedIn, founding year, Wuzzuf profile, role).

***

### ♻️ How to monitor Wuzzuf with incremental mode

Turn on **incremental mode** (`incrementalMode`) and schedule the Actor. Each run compares against the last one and tags each job with a `changeType`: **NEW**, **UPDATED**, **REAPPEARED** or **EXPIRED**. Unchanged jobs are skipped and not charged. A job counts as UPDATED only when its content changes, so a new applicant or page view doesn't make it look changed.

| | First run (baseline) | Next run (nothing changed) |
|---|---|---|
| Records emitted and billed | all | **none** |

After the baseline, your cost tracks how much Wuzzuf changes, not how many jobs you watch:

| Daily churn | of 1,000 tracked | billable records | you save |
|---|---|---|---|
| 5 % | 1,000 | 50 | **95 %** |
| 15 % | 1,000 | 150 | **85 %** |
| 30 % | 1,000 | 300 | **70 %** |

Options: `stateKey` names the tracked search (it's derived from your settings if you leave it blank). `emitUnchanged` and `emitExpired` add UNCHANGED and EXPIRED records. `skipReposts` ignores a vacancy that's taken down and re-posted under a new id with the same title, company and location. EXPIRED is reported only by runs that read the whole search (`maxResults` 0 or above the search size), so a capped run never marks a live job as gone.

**Setup:** configure your search, turn on incremental mode with Max results 0, and run it once to seed the baseline. Then add a schedule (e.g. every morning) in the **Schedules** tab.

***

### 🔔 How to set up Wuzzuf alerts

Fill in only the channels you want. Each one fires independently, so a broken channel can't stop the scrape or the others. Credentials are secret inputs: encrypted, masked in the UI and never logged.

| Channel | What to configure |
|---|---|
| ✈️ **Telegram** | `telegramToken` (from @BotFather) + `telegramChatId` |
| 💬 **Slack** | `slackWebhookUrl` |
| 🎮 **Discord** | `discordWebhookUrl` |
| 🪝 **Webhook** | `webhookUrl` (+ optional `webhookHeaders`): a JSON POST for n8n, Make or Zapier |

`notificationLimit` sets how many jobs each message lists (1–20, default 5). Pair incremental mode with `notifyOnlyChanges` to hear only about new, updated and reappeared jobs, with no repeats across runs.

***

### 💡 What can you do with Wuzzuf data?

#### Find low-competition openings

Sort by `applicantCount` to see which roles have only a handful of applicants. `applicationsViewed` and `applicationsShortlisted` show which employers are actually reviewing candidates.

#### Build B2B lead lists of companies hiring in Egypt

The **Companies hiring** view turns a search into a prospect list with websites, LinkedIn pages and industries. It suits recruitment agencies, HR-tech, payroll and training vendors.

#### Benchmark salaries in Egypt and the Gulf

Turn on *Only jobs with a published salary* to get numeric monthly pay with currency, by role, career level, city and years of experience.

#### Track the Egyptian labour market

Count open roles by category, district, workplace type and career level over time. A daily schedule shows which sectors are expanding and how fast vacancies fill.

#### Power a job board, alert channel or AI pipeline

Feed a niche board or Telegram channel with fresh jobs, each posted once thanks to incremental mode. You can also drop compact JSON straight into an LLM context, an MCP tool or a vector store.

***

### 💰 How much does it cost to scrape Wuzzuf?

This Actor uses Apify's **pay-per-event** model: a small fee when a run starts, plus a fee for each job saved. The **Pricing** tab always shows the current numbers. Three things keep the bill down:

- **Site-side filters**: jobs you filter out are never fetched and never billed.
- **Free screens**: the salary and confidential-employer screens skip jobs before they're charged.
- **Incremental mode**: after the baseline you pay only for what changed.

***

### 🔌 Integrations & export

Export to **JSON, CSV, Excel** or an HTML table, or use the **REST API** and the **JavaScript / Python** clients. Run it on a **schedule**, connect it to **Google Sheets, Make, Zapier and n8n**, or call it as an **MCP tool** from AI agents.

Our other Middle East job boards: **Bayt.com Jobs Scraper**, **GulfTalent Job Scraper** and **NaukriGulf Jobs Scraper**, all with the same incremental monitoring and alerts.

***

### 🔗 Using the API

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")

run = client.actor("corvuslab/wuzzuf-jobs-scraper").call(run_input={
    "searchTerms": ["software engineer"],
    "countries": ["Egypt"],
    "workplace": ["remote", "hybrid"],
    "maxResults": 50,
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["title"], item["company"], item["applicantCount"])
```

***

### ❓ FAQ

**Why is the salary empty on most Wuzzuf jobs?** Most Wuzzuf employers keep the salary confidential. Only about 15% of jobs publish one. On the rest `salaryText` is `"Confidential"` and `salaryHidden` is `true`. Use **Only jobs with a published salary** or **Minimum monthly salary** to keep just the salaried ones. Skipped jobs are not charged.

**Does it extract emails or phone numbers?** No. Wuzzuf strips contact details from postings, and candidates apply through the site. You get the employer's website, LinkedIn and Facebook instead, which is usually a better starting point for B2B outreach.

**What do the applicant numbers mean, and how current are they?** `applicantCount` is how many people applied. `applicationsViewed`, `applicationsShortlisted`, `applicationsRejected` and `applicationsNotSelected` show what the employer has done with the applications, and `jobViews` counts page views. `applicantVolumeLabel` buckets the applicant count: *Low* (under 10), *Medium* (10–49), *High* (50+). All of them reflect the moment of the scrape, so schedule the Actor to follow how they move.

**Why does a job say "Confidential" instead of a company name?** About 14% of Wuzzuf jobs are posted anonymously and have no company profile. Turn on **Skip confidential employers** to drop them before they're billed.

**Why are some company fields empty?** Each employer fills in its own profile. Across jobs, industry is present on about 78%, website 72%, description 69%, founding year 43%, LinkedIn 31% and Facebook 26%. Gender preference appears only when the employer states one (about 12% of jobs).

**Which countries does Wuzzuf cover?** About 96% of live jobs are in Egypt. Saudi Arabia, the UAE, the United States and the United Kingdom have a few dozen each. Kuwait, Oman, Jordan, Lebanon, Iraq, Libya, Qatar, Bahrain, Algeria and Germany have a handful, so a run limited to those can return few or no jobs on a given day.

**How many jobs can I get?** All of them. Set `maxResults` to 0 to read every matching job, up to the whole board (around 5,400 live jobs). `maxResults` is a total across all your search terms and places.

***

### ⚖️ Is it legal to scrape Wuzzuf?

This Actor collects only **publicly available** job listings and company profiles. It does not log in or access private candidate data. You're responsible for how you use the data, in particular any personal information, and for complying with Wuzzuf's terms and applicable law, including Egypt's Personal Data Protection Law and the GDPR where they apply. Not affiliated with, endorsed by or sponsored by Wuzzuf or BasharSoft.

***

**Keywords:** wuzzuf scraper · wuzzuf jobs scraper · wuzzuf.net scraper · wuzzuf api · scrape wuzzuf jobs · egypt jobs scraper · egypt job listings · cairo jobs data · mena jobs scraper · gulf jobs scraper · job applicant data · companies hiring in egypt · egypt salary data · job monitoring · lead generation · export to CSV · export to Excel · no-code scraper · MCP tool for AI agents

# Changelog

This Actor's version history is a separate document: https://apify.com/corvuslab/wuzzuf-jobs-scraper/changelog.md

# Actor input Schema

## `searchTerms` (type: `array`):

Job titles, skills or keywords, e.g. "accountant" or "python developer". Each term runs as its own search; results are merged and de-duplicated. Leave empty for all jobs.

## `countries` (type: `array`):

Only jobs in these countries. Most jobs on the board are in Egypt; Gulf and other countries have fewer openings. Leave empty for all countries.

## `locations` (type: `array`):

Cities ("Cairo", "Giza", "Alexandria", "Riyadh") or districts ("New Cairo", "Nasr City", "Maadi", "6th of October"). "City, Country" works too. Places with no open jobs are skipped with a warning.

## `startUrls` (type: `array`):

Paste Wuzzuf search URLs (wuzzuf.net/search/jobs/?q=…, filters included), country pages (wuzzuf.net/jobs/egypt) or single job URLs (wuzzuf.net/jobs/p/…). When set, these replace the search form.

## `maxResults` (type: `integer`):

Maximum number of jobs to return in total, across all search terms and places. Set 0 for every matching job.

## `jobTypes` (type: `array`):

Employment type.

## `workplace` (type: `array`):

On-site, hybrid or remote.

## `careerLevels` (type: `array`):

Seniority of the role.

## `categories` (type: `array`):

The site's job categories.

## `postedWithin` (type: `string`):

Only jobs posted recently.

## `yearsOfExperience` (type: `integer`):

Your years of experience: only jobs whose required range includes this number (jobs with no stated range are kept).

## `onlyWithSalary` (type: `boolean`):

Skip jobs whose salary is confidential. Skipped jobs are not charged.

## `minSalary` (type: `integer`):

Only jobs whose published monthly salary reaches this amount (top of the range), in the job's own currency — EGP for Egypt. Implies a published salary. Skipped jobs are not charged.

## `excludeConfidential` (type: `boolean`):

Skip jobs posted by an anonymous ("Confidential") company — handy for lead lists. Skipped jobs are not charged.

## `includeApplicantInsights` (type: `boolean`):

Add how many people applied, how many applications the employer viewed, shortlisted and rejected, page views, and a demand label — handy for spotting low-competition openings.

## `includeCompanyProfile` (type: `boolean`):

Add the employer's website, LinkedIn, Facebook, industry, description, logo and founding year.

## `descriptionFormat` (type: `string`):

Which version(s) of the job description and requirements to include.

## `descriptionMaxLength` (type: `integer`):

Truncate descriptions and requirements to this many characters. 0 or empty = full text.

## `compact` (type: `boolean`):

Emit only the core fields (title, company, location, job type, career level, experience, salary, date, applicants). Ideal for AI agents and MCP clients.

## `excludeEmptyFields` (type: `boolean`):

Remove null, empty-string and empty-array fields from each record.

## `incrementalMode` (type: `boolean`):

Track jobs between runs and tag each with a changeType (NEW / UPDATED / REAPPEARED / UNCHANGED / EXPIRED). Unchanged jobs are skipped and not charged.

## `stateKey` (type: `string`):

Stable name for the tracked search. Leave empty to derive one automatically from your search settings.

## `emitUnchanged` (type: `boolean`):

Also emit records that have not changed since the previous run.

## `emitExpired` (type: `boolean`):

Emit a record for each job seen last time but gone now. Only reported by runs that read the whole search (Max results 0 or above the search size).

## `skipReposts` (type: `boolean`):

Skip a job that re-appears under a new id with the same title, company and location as one already tracked.

## `telegramToken` (type: `string`):

Bot token from @BotFather.

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

Chat or channel ID, e.g. "-100123456789" or "@yourchannel".

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

Slack incoming-webhook URL.

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

Discord incoming-webhook URL.

## `webhookUrl` (type: `string`):

Any HTTPS endpoint. Receives a JSON POST with the matched records — works with n8n, Make and Zapier.

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

Extra headers for the webhook request, e.g. {"Authorization": "Bearer xyz"}.

## `notificationLimit` (type: `integer`):

How many records to include in each notification message.

## `notifyOnlyChanges` (type: `boolean`):

In incremental mode, send notifications only for NEW, UPDATED and REAPPEARED jobs.

## `proxyConfiguration` (type: `object`):

Optional. Not needed — the actor works without a proxy. Enable it only if your runs get blocked.

## `maxRequestRetries` (type: `integer`):

How many times to retry a failed request before giving up on it.

## `ignoreUrlFailures` (type: `boolean`):

Skip start URLs that cannot be interpreted instead of failing the whole run.

## Actor input object example

```json
{
  "searchTerms": [
    "accountant"
  ],
  "maxResults": 25,
  "postedWithin": "any",
  "onlyWithSalary": false,
  "excludeConfidential": false,
  "includeApplicantInsights": true,
  "includeCompanyProfile": true,
  "descriptionFormat": "all",
  "compact": false,
  "excludeEmptyFields": false,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "skipReposts": false,
  "notificationLimit": 5,
  "notifyOnlyChanges": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "maxRequestRetries": 3,
  "ignoreUrlFailures": true
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `allItems` (type: `string`):

No description

## `companies` (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 = {
    "searchTerms": [
        "accountant"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("corvuslab/wuzzuf-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 = { "searchTerms": ["accountant"] }

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

```

## MCP server setup

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