# GCC Jobs Aggregator - Bayt, GulfTalent & NaukriGulf (`jobsapi/gcc-jobs-search-scraper`) Actor

Search public Bayt, GulfTalent and NaukriGulf listings in one run and return deduplicated Gulf job records with seniority and optional Arabic labels.

- **URL**: https://apify.com/jobsapi/gcc-jobs-search-scraper.md
- **Developed by:** [Jobs API](https://apify.com/jobsapi) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.99 / 1,000 gcc jobs job records

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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 Aggregator

Searches public Bayt, GulfTalent, and NaukriGulf pages, or extracts one/multiple supported job URLs directly. Records are detail-verified, deduplicated, and normalized with title, company, GCC location, description, salary, posting date, skills, seniority, source-published labels/sections, application evidence, and direct-access provenance.

### Modes

- `search`: generate searches from `keywords`, `locations`, and `sources`, discover job links, then enrich detail pages.
- `single`: extract exactly one supported public job URL.
- `multiple`: extract up to 100 supported public job URLs sequentially.

Use `maxItems` to bound the requested dataset. Requests use fixed ordinary direct HTTPS settings with a bounded timeout, polite spacing, no retries, no proxy, and no fingerprint or identity changes. `includeArabic` retains optional Arabic labels. Only HTTPS URLs on Bayt, GulfTalent, and NaukriGulf hosts are accepted.

Each source is tracked independently. An HTTP 401/403/429/451 or visible verification/access-denial challenge stops that source and records it as `SKIPPED`; the actor does not retry, switch routes, or use a proxy. HTTP 407 and unverified transport failures are recorded as `DEFERRED`. Other available sources continue, and the run summary preserves each source's access evidence.

The dataset contains jobs only. Source failures and no-data explanations are stored in the `OUTPUT` run summary, preventing diagnostics from being mistaken for jobs. Public search layouts can change or withhold server-rendered results; direct URL modes are the most deterministic fallback.

### Run status and result status

The summary's `status` is the Apify platform outcome and is limited to `SUCCEEDED` or `FAILED`. `resultStatus` separately describes data completeness: `COMPLETE`, `LIMITED`, `SKIPPED`, `DEFERRED`, `NO_DATA`, or `FAILED`. `records` and `emittedRecords` count only complete job records whose Dataset push resolved successfully. A 401/403/429/451 response or visible source-authored challenge is `SKIPPED` only when its HTTPS receipt's requested and final URLs both match the same requested first-party source; then requests stop for that source, its unpersisted rows are discarded, and other requested sources may continue. Redirects are not followed. Cross-source responses, generic HTTP errors, proxy-authentication responses, uncertain transport, parser ambiguity, and unexplained empty results remain `DEFERRED`; this Actor has no affirmative empty-search detector and does not infer `NO_DATA`. Diagnostics and failed/block request receipts stay in key-value artifacts; successful per-job response receipts may accompany the corresponding real job row. Diagnostics are never written as Dataset rows. A fatal zero-row failure uses the Actor failure lifecycle; later non-block failures after successful Dataset writes preserve those rows as `SUCCEEDED` / `LIMITED`.

```json
{ "mode": "search", "keywords": ["software engineer"], "locations": ["Dubai"], "sources": ["gulftalent"], "maxItems": 20 }
```

### Local QA

```bash
npm test
npm run lint
npx apify validate-schema
```

An Actor run or dataset validator can read/write local storage. Before using either, follow the isolated-storage and preservation guidance in [`AGENTS.md`](AGENTS.md); this lifecycle audit did not run the Actor or inspect local storage.

# Actor input Schema

## `mode` (type: `string`):

Search configured GCC sources or fetch one/multiple supported public job pages.

## `jobUrls` (type: `array`):

Public Bayt, GulfTalent, or NaukriGulf HTTPS job URLs for direct modes.

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

One or more job keywords.

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

Cities or GCC countries such as UAE, Saudi Arabia, Qatar, Kuwait, Bahrain, or Oman.

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

Sources to search. A source that displays an explicit access barrier is stopped and recorded as skipped; other sources continue.

## `searchUrls` (type: `array`):

Optional public HTTPS search pages on a supported source. They are read in addition to generated searches.

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

Maximum deduplicated, detail-verified job records to return.

## `includeArabic` (type: `boolean`):

Keep optional Arabic title and location labels supplied by a source.

## Actor input object example

```json
{
  "mode": "search",
  "keywords": [
    "software engineer"
  ],
  "locations": [
    "United Arab Emirates"
  ],
  "sources": [
    "bayt",
    "gulftalent",
    "naukrigulf"
  ],
  "maxItems": 100,
  "includeArabic": false
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

## `runSummary` (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("jobsapi/gcc-jobs-search-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 = {}

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

```

## MCP server setup

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