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

Bayt Scraper - Gulf & MENA Jobs & Salary Data API

Pricing

from $2.23 / 1,000 job listings

Go to Apify Store
Bayt Scraper - Gulf & MENA Jobs & Salary Data API

Bayt Scraper - Gulf & MENA Jobs & Salary Data API

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.

Pricing

from $2.23 / 1,000 job listings

Rating

0.0

(0)

Developer

ParseForge

ParseForge

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Share

ParseForge

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 itWhat they scrape Bayt for
RecruitersWhich roles a city is hiring for right now, and who is posting them
Talent-intelligence teamsSalary benchmarks by role, seniority, and Gulf market
Compensation analystsPublished pay ranges in AED, SAR, QAR, and USD
Market researchersWhich companies are expanding into which MENA markets
Job boards and aggregatorsPublic 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 marketsUAE, 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 onpostedAt is an exact ISO timestamp taken from Bayt's own data. postedAtText keeps the original "3 hours ago".
Newest jobs firstSorts by date by default. Bayt's own relevance sort reaches back over 200 days.
Aggregation transparencyisAggregated 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 pagesBayt's pagination links drop your sort and filters. This Actor carries them through every page.
Four export formatsCSV, 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.

FeatureParseForgeblackfalcondatashahidirfaneasyapimakework36crawlerbros
Salary parsed into min / max / currencyYes, 11 currenciesNative and USD"salaries"Not statedNot stated"salaries"
Exact ISO posting date, not "15 days ago"Yes, plus original textNot statedNot statedNot statedNot statedNot stated
Aggregated-listing flag with published coverage figuresYes, isAggregatedNoNoNoNoNo
Sorted newest-first by defaultYesNot statedNot statedNot statedNot statedNot stated
Markets covered1812MENA, unspecifiedNot statedUAE, KSA, EG, QA, KW + moreNot stated
Field count4760+Not statedNot stated5 coreNot 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:

{
"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 goalHow to searchSalary presentCareer level present
Salary benchmarkingCountry, no keyword53%87%
Broad role researchCountry + keyword7%30%
Specific openings in one cityCountry + keyword + city2%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:

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

Track a role in one city:

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

Reproduce an existing Bayt search, filters and all:

{ "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.

FilterValues
datePostedPast 24 hours, 7 days, 30 days
employmentTypeFull time, Part time, Contractor, Temporary, Internship, Freelance
careerLevelStudent/Internship, Fresh graduate, Entry, Mid career, Management, Director/Head, Senior executive
industry22 industries, from Oil & Gas to IT Services
companyTypePrivate employer, Recruitment agency, Public employer, Non-profit
companyNameOne employer by name
directEmployersOnlySee 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:

ListingsAggregatedCareer level present
Off1091
On403

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:

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

Every senior opening at one employer:

{ "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 / descriptionHtmlThe complete posting, as text and as Bayt's original markup
skillsSkills and qualifications the employer lists
yearsOfExperience / monthsOfExperienceAs written, and as a number you can sort on
educationMinimum degree required
expiresAtApplication deadline, so a re-run can drop stale rows
detailSalaryMin / Max / Currency / PeriodA numeric salary range, on listings where the card shows none
vacancies, directApply, ageRange, residenceLocationThe rest of the employer's requirements
addressLocality / addressRegion / countryCodeStructured 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.

{ "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:

maxItemsRelevance: median age / over 30 daysDate: median age / over 30 days
1015 days / 24 days / 0
2014 days / 46 days / 0
3014 days / 413 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.

EventNo discountBronzeSilverGold
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.
RunApproximate 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 groupResult
UNBLOCKER (default)Works on the first request, no retries needed
RESIDENTIALBlocked on every attempt
No proxyBlocked

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

QuestionAnswer
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.

Browse the full ParseForge collection 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.