# GCC Jobs Scraper 🇦🇪 (Bayt, GulfTalent, NaukriGulf) (`tagadanar/gcc-jobs-scraper`) Actor

Every job matching your keywords on Bayt, GulfTalent and NaukriGulf across the UAE, Saudi Arabia, Qatar, Kuwait, Oman and Bahrain, in one table: title, company, city, salary, experience, nationality, posted date, description. Cross-board duplicates are flagged. No login.

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

## Pricing

from $0.70 / 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.
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

## GCC Jobs Scraper: Bayt, GulfTalent and NaukriGulf in one table

Type a job title, pick the Gulf countries or cities you care about, and get every matching job from **Bayt.com, GulfTalent and NaukriGulf** in one flat table: title, company, city, salary band, experience, career level, nationality requirement, posted date and the job description. When the same job is posted on two boards, the second copy is flagged with a link to the first, so you can count real openings instead of listings.

Built for recruiters and staffing agencies in the UAE and Saudi Arabia, job-market analysts tracking hiring by role and city, job aggregators that need a Gulf feed, and B2B sales teams looking for companies that are hiring right now.

$1.00 per 1,000 jobs, platform usage included. No login, no API key, no proxy setup.

### What you get

One row per job:

| Field | Description |
| --- | --- |
| `source` | `Bayt`, `GulfTalent` or `NaukriGulf` |
| `jobId`, `url` | The job's ID and page on that board |
| `title` | Job title as posted |
| `company`, `companyUrl` | Employer (or recruiter) and its page on the board. Null when the board hides a confidential employer |
| `city`, `country` | Where the job is, e.g. `Dubai`, `United Arab Emirates` |
| `salaryText` | Salary exactly as the board shows it, e.g. `AED 8,000 - AED 12,000` |
| `salaryMin`, `salaryMax`, `salaryCurrency` | The same salary as numbers plus the currency, when the board gives one |
| `experience`, `experienceMinYears`, `experienceMaxYears` | Experience asked for, e.g. `3-6 years` |
| `careerLevel` | Bayt's career level or GulfTalent's seniority (`Mid career`, `Supervisor / Manager`...) |
| `employmentType` | Full-time, part-time, contract... (GulfTalent) |
| `postedDate` | Posting date as an ISO timestamp |
| `postedText` | The date as Bayt prints it (`Yesterday`, `3 days ago`) |
| `descriptionSnippet` | A short summary of the job |
| `description` | Full job description as plain text (NaukriGulf and GulfTalent) |
| `skills` | Skills tagged on the job (NaukriGulf) |
| `industry`, `jobFunction` | Industry and job function (GulfTalent) |
| `nationalityRequirement` | When the job states one, e.g. `Saudi nationals`, `Any Nationality`, `India, Philippines` |
| `vacancies` | Number of openings, when stated (NaukriGulf) |
| `isEasyApply` | True when the board offers one-click apply |
| `searchKeyword`, `searchLocation` | Which of your searches found the job |
| `duplicateOf` | Set when the same job (same company, title and city) was already delivered from another board in this run: the URL of that first copy. Null otherwise |
| `capturedAt` | When the row was collected |

Not every board publishes every field. Bayt shows salary bands and nationality on the results page; GulfTalent gives industry, seniority, salary and nationality; NaukriGulf gives the full description, experience range and skills. GulfTalent's salary, nationality and description come from each job's own page, which the actor opens for the first 150 GulfTalent jobs of a run; later GulfTalent rows carry the listing fields only. Missing values are `null`, never guessed.

#### Example row (real, from a run on 2026-10-16, description shortened here)

```json
{
  "source": "GulfTalent",
  "jobId": "640870",
  "url": "https://www.gulftalent.com/uae/jobs/scaffolding-engineer-640870",
  "title": "Scaffolding Engineer",
  "company": "Al Ashram Contracting",
  "companyUrl": "https://www.gulftalent.com/companies/al-ashram-contracting-careers",
  "city": "Dubai",
  "country": "United Arab Emirates",
  "salaryText": "13000 - 16000 AED",
  "salaryMin": 13000,
  "salaryMax": 16000,
  "salaryCurrency": "AED",
  "experience": null,
  "experienceMinYears": null,
  "experienceMaxYears": null,
  "careerLevel": "Experienced professional",
  "employmentType": "Full-time",
  "postedDate": "2026-09-28T05:00:00.000Z",
  "postedText": null,
  "descriptionSnippet": "We are seeking a skilled and detail-oriented Scaffolding Engineer to join our dynamic construction team in Dubai. The ideal candidate will be responsible for the design, planning, and execution of scaffolding systems to ensure safe and efficient work environments on various construction projects...",
  "description": "We are seeking a skilled and detail-oriented Scaffolding Engineer to join our dynamic construction team in Dubai. The ideal candidate will be responsible for the design, planning, and execution of scaffolding systems to ensure safe and efficient work environments on various construction ...",
  "skills": [],
  "industry": "Construction",
  "jobFunction": "Engineering - Civil & Construction",
  "nationalityRequirement": "Any Nationality",
  "vacancies": null,
  "isEasyApply": true,
  "searchKeyword": "engineer",
  "searchLocation": "United Arab Emirates",
  "duplicateOf": null,
  "capturedAt": "2026-10-15T23:33:28.681Z"
}
```

### Input

| Field | What it does |
| --- | --- |
| `keywords` | Job titles or skills, one per line: `accountant`, `sales manager`, `SAP FICO`, `staff nurse` |
| `locations` | GCC countries or cities, one per line. Countries: United Arab Emirates (UAE), Saudi Arabia (KSA), Qatar, Kuwait, Oman, Bahrain. Cities: Dubai, Abu Dhabi, Sharjah, Ajman, Al Ain, Fujairah, Ras Al Khaimah, Umm Al Quwain, Riyadh, Jeddah, Dammam, Al Khobar, Jubail, Yanbu, Mecca, Medina, Dhahran, Doha, Kuwait City, Muscat, Salalah, Sohar, Manama |
| `sources` | Which boards to search. All three by default |
| `postedWithinDays` | Only jobs posted in the last N days (1 = today's jobs, 7 = this week). Empty = every open job |
| `maxJobsPerSearch` | Stop after this many jobs per keyword, per location, per board (default 100) |

Every keyword is searched in every location on every board you pick. With 2 keywords, 2 countries, 3 boards and 100 jobs per search you get up to 1,200 rows.

#### Accountant jobs in the UAE

```json
{
    "keywords": ["accountant"],
    "locations": ["United Arab Emirates"],
    "maxJobsPerSearch": 30
}
```

#### This week's sales and nursing jobs in Riyadh and Jeddah

```json
{
    "keywords": ["sales manager", "staff nurse"],
    "locations": ["Riyadh", "Jeddah"],
    "postedWithinDays": 7,
    "maxJobsPerSearch": 200
}
```

#### Engineering jobs in Qatar on Bayt and NaukriGulf only

```json
{
    "keywords": ["civil engineer", "mechanical engineer"],
    "locations": ["Qatar"],
    "sources": ["bayt", "naukrigulf"],
    "maxJobsPerSearch": 100
}
```

### Pricing

Pay per result, platform usage included:

| | Per 1,000 jobs |
| --- | --- |
| Free plan | $1.00 |
| Bronze | $0.90 |
| Silver | $0.80 |
| Gold | $0.70 |

Plus $0.001 once per run. A search a board has nothing for costs nothing. GulfTalent listings that GulfTalent itself marks as closed are left out and never charged.

### Use cases

- **Recruiters and staffing agencies**: see every open accountant, nurse or site engineer role in Dubai or Riyadh across the three big Gulf boards, with the employer and the salary band, and find the companies hiring for the roles you place.
- **B2B sales**: build a list of companies hiring in the UAE or Saudi Arabia this week (a hiring company is a buying company), filtered by role.
- **Job-market analysts**: track demand and salary bands by title, city and nationality requirement, week over week.
- **Job aggregators and job sites**: one de-duplicated Gulf feed instead of three scrapers to maintain.

### FAQ

**Which countries and cities can I search?**
The six GCC countries (UAE, Saudi Arabia, Qatar, Kuwait, Oman, Bahrain) and the main cities listed above. GulfTalent has no Medina or Sohar filter, so those cities are searched on Bayt and NaukriGulf only, and the run says so.

**How are duplicates handled?**
A job found by two of your keywords or locations on the same board is delivered once. A job posted on two boards (same company, same title, same city) is delivered from both, because each board carries different details (one has the salary, the other the full description), and the later copy has `duplicateOf` set to the first copy's URL. Filter on `duplicateOf` being empty to count unique openings.

**Why does a search return fewer jobs than I asked for?**
Because the board has fewer. The run's status line says, board by board, which searches ran out and at how many, which boards had nothing, and which were older than your posted-within window. A board that refused a request is named too, never shown as a silent zero.

**What happens when a job board is busy or refuses?**
Bayt and GulfTalent sometimes turn automated visitors away for a while. The run then tries other routes, and if a board still refuses, it delivers what the other boards have and its status line names the board that refused ("Bayt refused ... retry later"). You are only charged for the jobs delivered, so a retry later costs nothing extra.

**Does it get the salary?**
When the employer published one. Bayt shows a salary band on many listings, GulfTalent on some job pages. NaukriGulf does not show salaries on its listings, so its rows have `salaryText` empty.

**Can I get only new jobs every day?**
Set `postedWithinDays` to 1 and schedule the actor daily. Each run then returns the jobs posted in the last 24 hours.

**Do I need a Bayt, GulfTalent or NaukriGulf account?**
No. The actor reads the public job listings, the same pages anyone can open without logging in.

**Is there a Bayt scraper, GulfTalent scraper or NaukriGulf scraper on its own?**
This is all three in one. Use the `sources` field to search a single board, e.g. `["bayt"]` for a Bayt jobs scraper.

### Related actors

- [Naukri Jobs Scraper](https://apify.com/tagadanar/naukri-scraper): the same kind of feed for India's largest job board.
- [LinkedIn Jobs Scraper](https://apify.com/tagadanar/linkedin-jobs-scraper): LinkedIn job postings with hiring signals, for the roles that are only posted there.
- [LinkedIn Company Jobs Scraper](https://apify.com/tagadanar/linkedin-company-jobs): every open role at one company, to qualify an employer you found here.
- [Glassdoor Jobs Scraper](https://apify.com/tagadanar/glassdoor-jobs-scraper): jobs with the employer's Glassdoor rating on every row.

Keywords: Gulf jobs scraper, GCC jobs API, Bayt scraper, Bayt.com jobs scraper, GulfTalent scraper, NaukriGulf scraper, UAE jobs scraper, Dubai jobs scraper, Saudi Arabia jobs scraper, KSA jobs data, Qatar jobs, Kuwait jobs, Oman jobs, Bahrain jobs, Middle East job postings, salary data UAE.

# Changelog

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

# Actor input Schema

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

One job title or skill per line, the way you would type it into Bayt or GulfTalent: "accountant", "sales manager", "SAP FICO", "nurse". Each keyword is searched on every job board you pick, in every location.

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

One GCC country or city per line. Countries: United Arab Emirates (or UAE), Saudi Arabia (or KSA), Qatar, Kuwait, Oman, Bahrain. Cities: Dubai, Abu Dhabi, Sharjah, Ajman, Al Ain, Fujairah, Ras Al Khaimah, Umm Al Quwain, Riyadh, Jeddah, Dammam, Al Khobar, Jubail, Yanbu, Mecca, Medina, Dhahran, Doha, Kuwait City, Muscat, Salalah, Sohar, Manama. Leave empty for the UAE.

## `sources` (type: `array`):

Which job boards to search. All three by default.

## `postedWithinDays` (type: `integer`):

Only jobs posted in the last N days, for example 1 for today's jobs or 7 for this week. Leave empty for every open job.

## `maxJobsPerSearch` (type: `integer`):

Stop after this many jobs for each keyword in each location on each job board. With 2 keywords, 1 location and 3 boards, 100 means up to 600 jobs. You only pay for jobs delivered.

## Actor input object example

```json
{
  "keywords": [
    "accountant"
  ],
  "locations": [
    "United Arab Emirates"
  ],
  "sources": [
    "bayt",
    "gulftalent",
    "naukrigulf"
  ],
  "maxJobsPerSearch": 30
}
```

# Actor output Schema

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

One item per job in the default dataset.

# 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 = {
    "keywords": [
        "accountant"
    ],
    "locations": [
        "United Arab Emirates"
    ],
    "maxJobsPerSearch": 30
};

// Run the Actor and wait for it to finish
const run = await client.actor("tagadanar/gcc-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 = {
    "keywords": ["accountant"],
    "locations": ["United Arab Emirates"],
    "maxJobsPerSearch": 30,
}

# Run the Actor and wait for it to finish
run = client.actor("tagadanar/gcc-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 '{
  "keywords": [
    "accountant"
  ],
  "locations": [
    "United Arab Emirates"
  ],
  "maxJobsPerSearch": 30
}' |
apify call tagadanar/gcc-jobs-scraper --silent --output-dataset

```

## MCP server setup

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