# Bayt Scraper - Gulf & MENA Jobs & Salary Data API (`parseforge/bayt-scraper`) Actor

Scrape public Bayt.com job listings across all 18 Gulf and MENA markets. Parsed salary ranges, exact posting dates, seniority, and an aggregated-listing flag. No API key.

- **URL**: https://apify.com/parseforge/bayt-scraper.md
- **Developed by:** [ParseForge](https://apify.com/parseforge) (community)
- **Categories:** Jobs, Lead generation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.23 / 1,000 job listings

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/platform/actors/running/actors-in-store#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

[![ParseForge](https://raw.githubusercontent.com/ParseForge/apify-assets/main/banner.jpg)](https://apify.com/parseforge?fpr=vmoqkp)

### Bayt Scraper - Gulf & MENA Jobs & Salary Data API

**A Bayt job board scraper for salary and hiring analysis across all 18 Gulf and MENA markets.** Scrape public job listings from Bayt.com, the Middle East's largest job board — from the UAE and Saudi Arabia to Egypt, Morocco, and Pakistan — filtered by date, employment type, seniority, industry, or employer, the same way Bayt's own search filters them. Every listing comes with its published salary range, seniority, exact posting date, and a flag telling you whether Bayt hosts the job or aggregated it from elsewhere. No login or API key. Export to CSV, JSON, Excel, or XML.

Bayt has no public API. Search pages sit behind Cloudflare and sort by relevance, which quietly mixes in jobs posted months ago. This Actor reads the public search feeds directly, sorts by date so you get current openings, parses salary strings into numbers, and returns every match in one fixed schema.

| Who uses it | What they scrape Bayt for |
| --- | --- |
| Recruiters | Which roles a city is hiring for right now, and who is posting them |
| Talent-intelligence teams | Salary benchmarks by role, seniority, and Gulf market |
| Compensation analysts | Published pay ranges in AED, SAR, QAR, and USD |
| Market researchers | Which companies are expanding into which MENA markets |
| Job boards and aggregators | Public listings for approved aggregation workflows |

### What it does

This Actor collects Bayt job listings by keyword, country, and city, and returns each one as a flat row. Every listing carries:

- 🧾 **Core fields**: title, company, location, city, country, and canonical job URL.
- 💰 **Salary**: the published range plus parsed `salaryMin`, `salaryMax`, and `salaryCurrency`.
- 📅 **Exact dates**: `postedAt` as a real ISO 8601 timestamp, not "15 days ago".
- 🚩 **Flags**: remote, featured, and aggregated-from-third-party.
- 📝 **Summary**: the role summary shown on the listing card.
- 🏢 **Employer**: company name and its Bayt company-profile URL.

Results export to CSV, JSON, Excel, or XML, or stream from the API.

### What you can do with Bayt data

💰 **Benchmark salaries across the Gulf.**

Run the same job title across `uae`, `saudi-arabia`, and `qatar`, then compare `salaryMin` and `salaryMax` by `careerLevel`. Currencies are parsed, so the numbers are ready to chart.

📈 **Track hiring demand by city.**

Scrape `software engineer` in Dubai, Abu Dhabi, and Riyadh on a schedule and watch the volume and freshness of postings move week over week.

🎯 **Find companies that are actively hiring.**

Sort by date, filter to `isAggregated: false`, and you get employer-posted roles with a company profile link — the ones worth a sales or recruiting outreach.

🧠 **Build MENA labor-market datasets.**

Collect thousands of listings with summaries, seniority, and timestamps for a labeled corpus of real regional hiring activity.

### Why choose this scraper

Most Bayt scrapers return the search card as-is: a title, a company, and "15 days ago" as a string. That is fine for browsing and useless for analysis — you cannot sort by a relative date, average a salary that is still text, or trust a dataset where most rows came from a third-party feed with no salary at all.

This one is built for the analysis step:

| What you get | |
| --- | --- |
| **All 18 Bayt markets** | UAE, Saudi Arabia, Qatar, Kuwait, Bahrain, Oman, Egypt, Jordan, Lebanon, Iraq, Yemen, Morocco, Algeria, Tunisia, Libya, Pakistan, India, and International. |
| **Salary parsed, not just copied** | `$3,000 - $4,000` becomes `salaryMin: 3000`, `salaryMax: 4000`, `salaryCurrency: "USD"`. Handles USD, EUR, GBP, AED, SAR, QAR, KWD, BHD, OMR, EGP, and JOD. |
| **Real dates you can sort on** | `postedAt` is an exact ISO timestamp taken from Bayt's own data. `postedAtText` keeps the original "3 hours ago". |
| **Newest jobs first** | Sorts by date by default. Bayt's own relevance sort reaches back over 200 days. |
| **Aggregation transparency** | `isAggregated` tells you which rows are employer postings and which came from a third-party feed. Third-party rows carry no salary or seniority anywhere on Bayt — now you can filter them out. |
| **Filters carried across pages** | Bayt's pagination links drop your sort and filters. This Actor carries them through every page. |
| **Four export formats** | CSV, JSON, Excel, and XML, from the dashboard or the API. |

### How it compares

Bayt is a crowded niche — more than a dozen actors scrape it, and most return the same search card. Two things separate them in practice: whether the salary and date arrive as usable values, and whether you are told that roughly nine out of ten keyword-search rows are third-party aggregated listings that carry no salary at all.

The competitor columns below reflect what each Actor's own public listing states, not a test run of it.

| Feature | ParseForge | blackfalcondata | shahidirfan | easyapi | makework36 | crawlerbros |
| --- | --- | --- | --- | --- | --- | --- |
| Salary parsed into min / max / currency | Yes, 11 currencies | Native and USD | "salaries" | Not stated | Not stated | "salaries" |
| Exact ISO posting date, not "15 days ago" | Yes, plus original text | Not stated | Not stated | Not stated | Not stated | Not stated |
| Aggregated-listing flag with published coverage figures | Yes, `isAggregated` | No | No | No | No | No |
| Sorted newest-first by default | Yes | Not stated | Not stated | Not stated | Not stated | Not stated |
| Markets covered | 18 | 12 | MENA, unspecified | Not stated | UAE, KSA, EG, QA, KW + more | Not stated |
| Field count | 47 | 60+ | Not stated | Not stated | 5 core | Not stated |
| Price per result | $0.001 | $0.00099 | $0.00099 | $0.00299 | $0.0025 | $0.002 |

If you want the widest field set, `blackfalcondata/bayt-scraper` advertises 60+ fields at essentially the same price and is the most used actor in the niche. Come here when you need the salary and date as values you can sort and average, and when you need to know which rows are aggregated before you draw a conclusion from them.

### What a Bayt job looks like

Every listing returns as one flat JSON row. Here is a real record, unedited apart from a trimmed summary:

```json
{
  "jobId": "5477266",
  "title": "Sales Manager, UAE - L&D Training",
  "company": "Michael Page",
  "companyUrl": "https://www.bayt.com/en/company/michael-page-1528978/",
  "isAggregated": false,
  "location": "Dubai, UAE",
  "city": "Dubai",
  "country": "UAE",
  "salary": "$3,000 - $4,000",
  "salaryMin": 3000,
  "salaryMax": 4000,
  "salaryCurrency": "USD",
  "careerLevel": "Mid career",
  "isRemote": false,
  "isFeatured": false,
  "summary": "A dynamic Business Development Manager is sought, specializing in Training Sales for UAE clients. This role demands expertise in identifying new busin...",
  "postedAt": "2026-08-18T14:32:28.000Z",
  "postedAtText": "3 hours ago",
  "url": "https://www.bayt.com/en/uae/jobs/sales-manager-uae-l-d-training-5477266/",
  "searchUrl": "https://www.bayt.com/en/uae/jobs/?options%5Bsort%5D%5B%5D=d",
  "scrapedAt": "2026-08-18T18:35:29.399Z"
}
```

`city` is absent when Bayt lists only a country. Fields the employer did not publish are omitted rather than guessed.

#### How to get the richest data

Bayt mixes employer-posted jobs with listings pulled from third-party feeds, and the third-party ones carry no salary or seniority anywhere on Bayt. How much of each you get depends on how you search — so here is the measured breakdown, and how to search for what you need:

| Your goal | How to search | Salary present | Career level present |
| --- | --- | --- | --- |
| **Salary benchmarking** | Country, no keyword | **53%** | **87%** |
| Broad role research | Country + keyword | 7% | 30% |
| Specific openings in one city | Country + keyword + city | 2% | 9% |

**For compensation research, search by country and filter `isAggregated: false`** — that combination gives you employer-posted jobs with published pay. For finding specific openings, add the keyword and city and expect leaner metadata, since that is what Bayt's feed holds for those searches.

No other Bayt scraper tells you this, because none of them expose the aggregation flag that makes it measurable.

### Configure the run

Drive the Actor with a keyword, a country, and an optional city — or paste a Bayt search URL to reproduce a search exactly. The Input tab lists every parameter.

Benchmark salaries across a whole market:

```json
{ "country": "saudi-arabia", "sortBy": "date", "maxItems": 500 }
```

Track a role in one city:

```json
{ "keyword": "software engineer", "country": "uae", "city": "Dubai", "maxItems": 200 }
```

Reproduce an existing Bayt search, filters and all:

```json
{ "searchUrl": "https://www.bayt.com/en/qatar/jobs/nurse-jobs/", "maxItems": 300 }
```

#### Filters

Every filter below is a parameter on Bayt's own search, so a filtered run costs exactly the same as an unfiltered one — there is no extra request and no extra page.

| Filter | Values |
| --- | --- |
| `datePosted` | Past 24 hours, 7 days, 30 days |
| `employmentType` | Full time, Part time, Contractor, Temporary, Internship, Freelance |
| `careerLevel` | Student/Internship, Fresh graduate, Entry, Mid career, Management, Director/Head, Senior executive |
| `industry` | 22 industries, from Oil & Gas to IT Services |
| `companyType` | Private employer, Recruitment agency, Public employer, Non-profit |
| `companyName` | One employer by name |
| `directEmployersOnly` | See below |

**`directEmployersOnly` is the one no other Bayt scraper has.** Most of a keyword search is aggregated repostings pulled from third-party boards, and those rows carry almost no structured data. This flag pins the search to direct private-sector employers *and* drops any aggregated row that slips through — and because they are dropped before anything is written, you are never charged for them.

It trades volume for quality, and the trade is steep. Same search for "software engineer" in Dubai, measured:

| | Listings | Aggregated | Career level present |
| --- | --- | --- | --- |
| Off | 10 | 9 | 1 |
| **On** | **4** | **0** | **3** |

Turn it on when you are going to act on the rows one by one and the junk costs you time. Leave it off when you want the widest possible view of a market.

Only jobs posted in the last 24 hours, full time, by the employer itself:

```json
{ "country": "uae", "datePosted": "24h", "employmentType": "full-time", "directEmployersOnly": true, "maxItems": 500 }
```

Every senior opening at one employer:

```json
{ "country": "uae", "companyName": "Al Futtaim Group", "careerLevel": "senior-executive", "maxItems": 100 }
```

#### Full job details

A search card carries what Bayt prints on the listing. The job's own page carries the rest, and `includeDetails` goes and gets it:

| From the job page | |
| --- | --- |
| `description` / `descriptionHtml` | The complete posting, as text and as Bayt's original markup |
| `skills` | Skills and qualifications the employer lists |
| `yearsOfExperience` / `monthsOfExperience` | As written, and as a number you can sort on |
| `education` | Minimum degree required |
| `expiresAt` | Application deadline, so a re-run can drop stale rows |
| `detailSalaryMin` / `Max` / `Currency` / `Period` | A numeric salary range, on listings where the card shows none |
| `vacancies`, `directApply`, `ageRange`, `residenceLocation` | The rest of the employer's requirements |
| `addressLocality` / `addressRegion` / `countryCode` | Structured address with an ISO country code |

This reads Bayt's own structured job-posting data rather than scraping the rendered page, so it survives redesigns that break selector-based scrapers.

**It is not free and it is not fast.** Each job means one extra request and about 25 seconds, run five at a time. A 100-listing run goes from roughly one minute to about eight, and the extra requests are billed as a separate `Job detail` event. Turn it on with a `maxItems` you actually need, not with 10,000.

```json
{ "country": "uae", "datePosted": "7d", "directEmployersOnly": true, "includeDetails": true, "maxItems": 50 }
```

#### Sorting and freshness

Bayt sorts by relevance by default, which surfaces listings posted months ago: in one measured search, 42% were over 30 days old and the oldest was 216 days. This Actor sorts by date instead.

Sorting orders results, it does not filter them, so the gain shows up whenever `maxItems` is smaller than the total result count. Same search, same 65 available listings:

| `maxItems` | Relevance: median age / over 30 days | Date: median age / over 30 days |
| --- | --- | --- |
| 10 | 15 days / 2 | **4 days / 0** |
| 20 | 14 days / 4 | **6 days / 0** |
| 30 | 14 days / 4 | **13 days / 0** |

Set `sortBy: "relevance"` if you would rather have Bayt's own ranking.

### Pricing

Pay-per-event, and every charge lands **after** the row is written, never before. Apify plan discounts apply automatically.

| Event | No discount | Bronze | Silver | Gold |
| --- | --- | --- | --- | --- |
| **Job listing** · `result-item` | **$1.00 / 1,000** | $0.96 / 1,000 | $0.93 / 1,000 | $0.89 / 1,000 |
| **Job detail** · `job-detail` | **$3.00 / 1,000** | $2.89 / 1,000 | $2.78 / 1,000 | $2.67 / 1,000 |
| **Search query** · `search-query` | **$2.00 / 1,000** | $1.93 / 1,000 | $1.85 / 1,000 | $1.78 / 1,000 |
| **Actor start** · `apify-actor-start` | **$0.002** | $0.0019 | $0.0019 | $0.0018 |

What each one means:

- **Job listing** — one row written to your dataset. This is the only charge a plain search incurs.
- **Job detail** — the job's own page, read only with `includeDetails`, and only when the page actually came back. One extra unblocking request per job, which is why it costs three times a listing.
- **Search query** — one keyword or search URL resolved. Charged **once per search**, and only after that search has produced a listing: paging through results is not a new search, and a search that returns nothing is not billed at all.

| Run | Approximate cost |
| --- | --- |
| 100 listings | $0.10 |
| 1,000 listings | $1.00 |
| 10,000 listings | $10.00 |

One search adds $0.002; ten keywords in one run add $0.02. With `includeDetails` on, add $0.003 per listing — 1,000 listings with job pages runs about $4.00.

**You do not pay platform usage costs.** Bayt needs a strong unblocking proxy and the compute to go with it; both are already covered by the prices above, so there is no separate Apify bill on top.

New Apify accounts start with $5 in free credit — about 5,000 job listings.

### Free users

Free-plan runs return up to **10 listings**, enough to check the data before committing. Bayt blocks ordinary requests, so every run goes through a paid unblocking proxy whose cost we absorb — the free cap keeps that sustainable.

Any paid Apify plan lifts it to 10,000 listings per run, and the $5 starting credit covers roughly 5,000 of them.

### Run it

1. Create a free Apify account with $5 in credit.
2. Open the **Bayt Scraper**.
3. Pick a `country`, add a `keyword` and `city` if you want to narrow it, set `maxItems`, and click **Start**.
4. Export the results as CSV, Excel, JSON, or XML from the **Dataset** tab.

Run it programmatically through the Apify API or the ApifyClient for JavaScript and Python.

#### Proxies

Bayt blocks datacenter and residential IPs aggressively, so this Actor defaults to Apify Proxy with the **UNBLOCKER** group, which gets through on the first request. Measured on the same search:

| Proxy group | Result |
| --- | --- |
| **UNBLOCKER** (default) | Works on the first request, no retries needed |
| RESIDENTIAL | Blocked on every attempt |
| No proxy | Blocked |

Its cost is included in the per-listing price, so you do not pay for it separately. Blocked pages are retried up to eight times with a fresh session and a new browser fingerprint each time.

If you point the Actor at a different proxy group and Bayt blocks it, the run **switches to UNBLOCKER automatically** after three blocked attempts instead of failing. And if the first page still never loads, the run fails with a clear message rather than handing you an empty dataset.

### Use with AI agents (MCP)

Give an AI agent live access to Gulf hiring data through the Model Context Protocol. Add the Actor to Claude, Cursor, or any MCP client:

```
claude mcp add --transport http apify "https://mcp.apify.com?tools=parseforge/bayt-scraper"
```

Then prompt it in plain language:

- "Find software engineering jobs posted in Dubai this week and list the ones with a salary range."
- "Compare published salaries for accountants in the UAE, Saudi Arabia, and Qatar."
- "Pull the 100 newest jobs in Egypt and group them by company."

Copy this into ChatGPT, Claude, or Cursor to start:

```
Use the Apify Actor "parseforge/bayt-scraper" to collect public Bayt.com job listings. Input: { "keyword": "<role>", "country": "<uae|saudi-arabia|qatar|kuwait|bahrain|oman|egypt|jordan|lebanon|iraq|yemen|morocco|algeria|tunisia|libya|pakistan|india|international>", "city": "<optional city>", "sortBy": "date", "maxItems": <n> }. It returns title, company, companyUrl, location, city, country, salary, salaryMin, salaryMax, salaryCurrency, careerLevel, isRemote, isAggregated, summary, postedAt, and url per listing. Call it with the ApifyClient and my APIFY_TOKEN.
```

### Troubleshooting

**Why am I getting no results?**

The city may not belong to the country you picked, or the keyword may have no matches in that market. Drop the `city` first, then the `keyword`, and confirm the country index returns jobs.

**How do I get more rows with salary?**

Search by country without a keyword, and filter to `isAggregated: false`. That takes salary coverage from about 7% to about 53%, because third-party aggregated listings do not carry salary anywhere on Bayt.

**Why fewer listings than I asked for?**

The search ran out of results. Bayt returns 30 per page, and a narrow keyword-plus-city search often holds only two or three pages. Widen the search or drop the city.

**Why am I getting HTTP 403?**

Your proxy group is being blocked. Set `proxyConfiguration` to the `UNBLOCKER` group — Bayt rejects datacenter and residential IPs. Its cost is already included in the per-listing price.

**Why is the run slow?**

Each page holds 30 listings, so a large `maxItems` fetches many pages, and blocked pages add backoff delay. Lower `maxItems` or split one job into scheduled runs.

**A field stopped filling.**

Bayt changed its page markup. Email us with your run ID so we can update the parser.

### FAQ

| Question | Answer |
| --- | --- |
| Do I need a Bayt account or API key? | No. Bayt has no public API. This reads public search pages, so there is nothing to register or authorize. |
| Which countries does it cover? | All 18 Bayt markets, including the six GCC states, Egypt, Jordan, Lebanon, Iraq, Yemen, Morocco, Algeria, Tunisia, Libya, Pakistan, and India. |
| Does it return salary data? | Yes, parsed into `salaryMin`, `salaryMax`, and `salaryCurrency` across eleven currencies. Search by country to reach about 53% coverage — see the table above. |
| What is `isAggregated`? | Bayt mixes its own employer postings with listings pulled from third-party feeds. Aggregated rows carry no salary or seniority, so this flag lets you filter to employer-posted jobs. |
| Can I filter by city? | Yes. Set `city` alongside `country`, for example Dubai, Riyadh, or Cairo. |
| Does it return the job description? | Every row carries the role summary shown on the listing, plus the canonical job URL so you can pull the full description for the roles you care about. |
| How many listings per run? | Up to 10,000 on any paid Apify plan, bounded by how many results the search holds. Free-plan runs return 10. |
| Do I need a proxy? | Yes, and it is already set up. The default `UNBLOCKER` group works out of the box, and its cost is included in the per-listing price. |
| Is this an official Bayt product? | No. It is unofficial and reads only public Bayt data. |

### Related actors

- [SEEK Australia Jobs Scraper](https://apify.com/parseforge/seek-scraper): job listings from Australia's largest job board.
- [Upwork Freelancers Scraper](https://apify.com/parseforge/upwork-freelancers-scraper): freelance talent profiles, rates, and skills.
- [LinkedIn Posts Scraper](https://apify.com/parseforge/linkedin-posts-scraper): public post content for employer-brand research.
- [Crunchbase Scraper](https://apify.com/parseforge/crunchbase-scraper): company funding and headcount for the employers you find.
- [UK Companies House Scraper](https://apify.com/parseforge/uk-companies-house-scraper): official company registry records.

[Browse the full ParseForge collection](https://apify.com/parseforge?fpr=vmoqkp) for more scrapers.

🆘 **Need help?** Email parseforge@protonmail.com with your run ID, your input, and what you expected.

⚠️ **Disclaimer.** This Actor is unofficial and is not affiliated with, endorsed by, or sponsored by Bayt.com Inc. It collects only publicly available job listings. You are responsible for using the data in compliance with Bayt's terms and applicable laws, including GDPR, CCPA, and PIPL. Do not use it to identify, profile, or target individuals.

# Actor input Schema

## `keyword` (type: `string`):

Job title, skill, or keyword. Leave empty to list every job in the selected country.

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

Run several searches in one go — one per keyword, against the same filters. Each search that returns at least one listing is billed as a single search-query event.

## `country` (type: `string`):

Bayt country section to search. Bayt encodes the country in the URL path, so this must be one of its supported markets.

## `city` (type: `string`):

Narrow the search to one city, for example Dubai or Riyadh. Must belong to the selected country.

## `sortBy` (type: `string`):

Bayt sorts by relevance by default, which mixes in listings posted months ago. Sort by date to get the newest jobs first.

## `datePosted` (type: `string`):

Only return jobs posted within this window. Past 24 hours turns a run into a daily delta instead of a full re-scrape: on a country-wide UAE search it is about 145 listings out of 9,640.

## `employmentType` (type: `string`):

Only return jobs of this contract type.

## `careerLevel` (type: `string`):

Only return jobs at this seniority, using Bayt's own levels.

## `industry` (type: `string`):

Only return jobs in this industry, using Bayt's own industry list.

## `directEmployersOnly` (type: `boolean`):

Return only jobs posted by the employer itself. This does two things Bayt's own filters cannot do alone: it pins the search to direct private-sector employers, and it drops aggregated repostings from third-party boards. Those repostings are 89% of a typical keyword search and almost never carry a salary. Rows dropped this way are never charged.

## `companyType` (type: `string`):

Filter by who is hiring. Ignored when "Direct employers only" is on, which pins this to private-sector employers.

## `companyName` (type: `string`):

Only return jobs from this employer, for example "Al Futtaim Group". Matches Bayt's own employer facet.

## `includeDetails` (type: `boolean`):

Open each job's own page to add the full description, skills, required experience and education, the application deadline, and a numeric salary range where Bayt publishes one. This is the difference between a listing row and the whole posting. It costs one extra request and about 25 seconds per job, and it is billed as a separate 'Job detail' event — so turn it on with a `maxItems` you actually need.

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

Full Bayt search-results URL. When set, it overrides the keyword, country, city, and sort fields.

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

Paste several Bayt search URLs straight from your browser. They override the filters above, and each one is billed as a search-query event.

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

Maximum number of public job listings to save. Bayt returns 30 per page, so the run follows pagination until it reaches this number. Free-plan runs are capped at 10 listings.

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

Bayt blocks datacenter and residential IPs. The UNBLOCKER group gets through reliably and its cost is included in the per-listing price. Only change it if you know your own IPs work.

## Actor input object example

```json
{
  "keyword": "software engineer",
  "keywords": [
    "accountant",
    "software engineer"
  ],
  "country": "uae",
  "city": "Dubai",
  "sortBy": "date",
  "datePosted": "any",
  "employmentType": "any",
  "careerLevel": "any",
  "industry": "any",
  "directEmployersOnly": false,
  "companyType": "any",
  "includeDetails": false,
  "searchUrl": "https://www.bayt.com/en/uae/jobs/software-engineer-jobs/",
  "searchUrls": [],
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "UNBLOCKER"
    ]
  }
}
```

# Actor output Schema

## `listings` (type: `string`):

One public Bayt job listing per dataset item.

# 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 = {
    "keyword": "software engineer",
    "keywords": [
        "accountant",
        "software engineer"
    ],
    "country": "uae",
    "city": "Dubai",
    "sortBy": "date",
    "datePosted": "any",
    "employmentType": "any",
    "careerLevel": "any",
    "industry": "any",
    "directEmployersOnly": false,
    "companyType": "any",
    "includeDetails": false,
    "maxItems": 100,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "UNBLOCKER"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("parseforge/bayt-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 = {
    "keyword": "software engineer",
    "keywords": [
        "accountant",
        "software engineer",
    ],
    "country": "uae",
    "city": "Dubai",
    "sortBy": "date",
    "datePosted": "any",
    "employmentType": "any",
    "careerLevel": "any",
    "industry": "any",
    "directEmployersOnly": False,
    "companyType": "any",
    "includeDetails": False,
    "maxItems": 100,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["UNBLOCKER"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("parseforge/bayt-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 '{
  "keyword": "software engineer",
  "keywords": [
    "accountant",
    "software engineer"
  ],
  "country": "uae",
  "city": "Dubai",
  "sortBy": "date",
  "datePosted": "any",
  "employmentType": "any",
  "careerLevel": "any",
  "industry": "any",
  "directEmployersOnly": false,
  "companyType": "any",
  "includeDetails": false,
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "UNBLOCKER"
    ]
  }
}' |
apify call parseforge/bayt-scraper --silent --output-dataset

```

## MCP server setup

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