Bayt.com Scraper - Salaries, Companies & Job Details
Pricing
from $1.00 / 1,000 results
Bayt.com Scraper - Salaries, Companies & Job Details
Scrape Bayt.com job listings by keyword, country, or URL. Extract structured data including job title, company, location, salary, experience, career level, posting date, work style, and full job description. Built for recruitment, job aggregation, market research, and workforce analytics.
Pricing
from $1.00 / 1,000 results
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
1
Bookmarked
116
Total users
3
Monthly active users
10 days ago
Last modified
Categories
Share
Bayt.com Scraper: Job Listings Across the Middle East
Bayt.com Scraper turns Bayt.com, the leading careers portal across the Middle East and North Africa, into structured job data. Search by country and keyword, or paste Bayt.com search links directly, and get every job listing's title, company, location, salary, career level, experience, work style and full description. Cover 15 markets, then export to JSON, CSV or Excel, or read the results through the API.
Why This Scraper?
- Two ways to search. Build a search from a country and keyword, or paste one or more Bayt.com search links and walk them forward.
- 15 markets covered. UAE, Saudi Arabia, Egypt, Qatar, Kuwait, Bahrain, Oman, Jordan, Lebanon, Iraq, Morocco, Tunisia, Algeria, Pakistan and International.
- Up to 37 fields per job. Salary range, career level, years of experience, work style, company industry and the full preferred-candidate criteria (residence location, nationality, gender, degree, major).
- Full detail by default. Fetch full job details is on by default and adds the complete description, employment type, posting and expiry dates, vacancies, and company size, billed as a small surcharge per job. Turn it off for a lighter, cheaper run.
- Forward pagination. Walks every result page (30 jobs per page) until the natural end, your page cap or your listing cap, whichever comes first.
- Built for schedules. Incremental mode returns only new and changed jobs on recurring runs, and it can resume one specific interrupted crawl instead.
Use Cases
- Recruitment and staffing: track new postings across a market or keyword to source candidates or benchmark competing roles.
- Market research and salary benchmarking: collect salary ranges, career levels and experience requirements across countries and industries.
- Job aggregators and boards: feed Bayt.com listings with full detail into your own site or app.
- Workforce and migration research: analyse preferred-candidate criteria such as nationality, residence location and degree requirements by market.
- Recurring monitoring: watch a search on a schedule and get only the jobs that are new or changed.
Data You Get
Sample shape: values are illustrative placeholders, not from a live record.
| Field | Example |
|---|---|
jobId / url | "00000001" / Bayt.com link to the job |
title / company / companyUrl | "Sample Job Title" / "Sample Company" / company profile link |
city / country / countrySlug | "Dubai" / "UAE" / "uae" |
salary | "AED 0 - AED 0" |
careerLevel / experience | "Mid career" / "0-4 Years of Experience" |
workStyle | "Hybrid" |
employmentType | "FULL_TIME" (when fetchDetails is on) |
postedDate / postedTimestamp | "1 day ago" / 1700000000 |
logo | company logo URL |
isExternal / isAggregated / easyApply | false / false / true |
aiSummary | short AI-generated summary of the role |
description | full job description text (when fetchDetails is on) |
datePosted / validThrough | "2026-01-01" / "2026-02-01T00:00:00Z" (when fetchDetails is on) |
vacancies | 1 (when fetchDetails is on) |
companyIndustry / companySize | "Sample Industry" / "10-49 Employees" (when fetchDetails is on) |
residenceLocation / nationality / gender / age / degree / major | preferred-candidate criteria (when fetchDetails is on) |
preferredCandidate | the same criteria, grouped in one object (when fetchDetails is on) |
directApply | true (when fetchDetails is on) |
jobCountryCode | "AE" (when fetchDetails is on) |
changeType / changedFields / firstSeenAt / lastSeenAt | incremental mode only |
scrapedAt | "2026-01-01T00:00:00.000Z" |
How to Use
- Pick a mode:
search(country plus keyword) orurl(paste Bayt.com search links). - For search mode, set the country and, optionally, a keyword. In URL mode, paste one or more search links; country and keyword are ignored.
- Set Max listings (and optionally Max pages) to control run size and cost, then click Start.
- Download the dataset as JSON, CSV or Excel, or read it through the API.
All jobs in one country:
{"mode": "search","country": "uae","maxPages": 3,"maxListings": 0}
Keyword search with a result cap:
{"mode": "search","country": "saudi-arabia","keyword": "software engineer","maxListings": 50}
Lightweight run without opening each job page:
{"mode": "search","country": "egypt","keyword": "accountant","fetchDetails": false}
Paste search links directly:
{"mode": "url","urls": ["https://www.bayt.com/en/uae/jobs/sales-jobs/","https://www.bayt.com/en/qatar/jobs/accountant-jobs/"],"maxPages": 2,"maxListings": 0}
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/bayt-com-jobs-scraper").call(run_input={"mode": "search", "country": "uae", "keyword": "accountant"})for job in client.dataset(run["defaultDatasetId"]).iterate_items():print(job["title"], job["company"], job["salary"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/bayt-com-jobs-scraper').call({ mode: 'search', country: 'uae', keyword: 'accountant' });const { items } = await client.dataset(run.defaultDatasetId).listItems();
Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.
Resume and recurring updates
- Resume (
resumeFromRunId) continues one specific interrupted or previous large crawl: paste a run ID or dataset ID and this run skips jobs already collected there, returning only the remaining new ones. - Incremental mode (
incrementalMode) is for a schedule, for example daily: the actor remembers the previous run of the same search by itself, so you never paste a run ID. The first run returns everything asNEW. Later runs return onlyNEW,UPDATED(withchangedFields) andREAPPEAREDjobs by default; unchanged jobs are suppressed and not billed unlessemitUnchangedis on.emitExpiredadds jobs no longer found, only after a run that fully scanned the tracked search.stateKeynames or shares a monitoring campaign.
Send results into your apps (MCP connectors)
Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.
What gets written to the connector: a condensed, human-readable summary of each record, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.
- Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
- Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
- For Notion, also set
notionParentPageUrlto the page where items should be created.
The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
mode | string | search | search builds a query from country plus keyword. url walks pasted Bayt.com search links. |
country | string | uae | Market to search in search mode. One of 15 supported countries. |
keyword | string | (none; prefilled accountant) | Optional job title or keyword in search mode, in English (Latin letters). Arabic or other non-Latin keywords are not applied and return all jobs in the country. Blank lists all jobs in the country. |
urls | array | (none; prefilled with one sample UAE search link) | One or more Bayt.com search URLs in URL mode. Country and keyword are ignored here. |
maxPages | integer | 0 | Result pages to walk per search (30 jobs per page). 0 means unlimited: the walk stops once a page comes back empty or repeats jobs already collected, or sooner once Max listings is reached. |
maxListings | integer | 20 | Stop after this many jobs across all searches. 0 = unlimited (bounded only by the natural stop on Max pages). |
fetchDetails | boolean | true | Open each job page for the full description and extra fields. Turn off for a faster, lighter run. |
resumeFromRunId | string | (none) | Continue one specific interrupted run. |
incrementalMode | boolean | false | Return only new and changed jobs on recurring runs. |
stateKey | string | (none) | Name or share an incremental-mode monitoring campaign. |
emitUnchanged | boolean | false | Also return (and bill) unchanged jobs. |
emitExpired | boolean | false | Also return (and bill) expired jobs. |
proxy | object | Residential | Connection settings. Residential is required; datacenter connections are rejected. |
mcpConnectors | array | (none) | Optional: send a summary of each job to apps you authorized under Integrations. |
notionParentPageUrl | string | (none) | Notion connector only: page under which job pages are created. |
maxNotifyListings | integer | 50 | Cap on items written to each connector per run. |
Output Example
Sample shape: values are illustrative placeholders, not from a live record.
{"jobId": "00000001","title": "Sample Job Title","url": "https://www.bayt.com/en/uae/jobs/sample-job-title-00000001/","company": "Sample Company","companyUrl": "https://www.bayt.com/en/company/sample-company-0000000/","city": "Dubai","country": "UAE","countrySlug": "uae","logo": "https://secure.b8cdn.com/58x58/images/logo/00/0000000_logo_0000000000_n.png","salary": "AED 0 - AED 0","careerLevel": "Mid career","experience": "0-4 Years of Experience","workStyle": "Hybrid","postedDate": "1 day ago","postedTimestamp": 1700000000,"isExternal": false,"isAggregated": false,"easyApply": true,"aiSummary": "Short AI generated summary of the role appears here.","description": "Full job description text appears here when fetchDetails is on.","employmentType": "FULL_TIME","datePosted": "2026-01-01","validThrough": "2026-02-01T00:00:00Z","vacancies": 1,"companyIndustry": "Sample Industry","companySize": "10-49 Employees","residenceLocation": "United Arab Emirates","nationality": "Sample Nationality","gender": "Any","age": "25 - 40 years","degree": "Bachelor's degree","major": "Sample Major","preferredCandidate": {"careerLevel": "Mid career","yearsOfExperience": "3+ years","residenceLocation": "United Arab Emirates","nationality": "Sample Nationality","gender": "Any","age": "25 - 40 years","degree": "Bachelor's degree","major": "Sample Major"},"jobCountryCode": "AE","directApply": true,"scrapedAt": "2026-01-01T00:00:00.000Z"}
Plan Requirement
Bayt.com only accepts residential connections, so keep the default Residential setting under Connection. If it cannot be used, the actor switches to a backup connection automatically, and you can also paste your own residential proxy URLs. Datacenter connections are rejected and return no results.
FAQ
How much does it cost?
You pay per job returned, with the full-detail fetch billed as a surcharge only for jobs where it successfully attaches. The Pricing tab shows the current rates. Use Max listings to cap the cost of any run.
Is it legal to scrape Bayt.com?
This actor collects only publicly available job listing data. You are responsible for how you use it: follow Bayt.com's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution.
Can I get only new or changed jobs on a schedule?
Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new, updated and reappeared jobs, and unchanged ones are not billed unless you turn on emitUnchanged.
Why did my run return zero jobs?
An empty result is normal when an Incremental mode run finds nothing new or changed, when the keyword has no matching jobs, or when URL mode has no links. Otherwise, Bayt.com only accepts residential connections; a datacenter or rejected exit IP returns zero jobs with a warning in the run log rather than failing the run. Keep the default residential proxy setting, re-run for a fresh exit IP, or paste your own residential proxy URLs. The run only fails outright when no connection at all can be set up, when resumeFromRunId matches no run or dataset your account can read, or when Incremental mode already has saved state and resumeFromRunId is also set.
Can I use it with AI agents or MCP?
Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.
🔗 Want more jobs data?
Pair this actor with these related scrapers from the same team:
| 💼 CareerBuilder Scraper Scrape CareerBuilder.com job listings by search or URL. Returns title, company profile... | 💼 JobTeaser Scraper Scrape early-career jobs and internships from JobTeaser across Europe. Search with 15... |
| 💼 Jora Jobs Scraper Scrape Jora.com job listings across supported countries by keyword, filters, or URL... | 💼 NIJobs Scraper Scrape NIJobs.com listings across Northern Ireland by keyword, location, salary, posted... |
| 📇 JobStreet From $1/1K. Pull JobStreet company profiles and employee reviews across Malaysia... | 💼 HH.ru Jobs Scraper From $1/1K. Scrape HH.ru job listings with 50+ structured fields. Search by filters or... |
💬 Support & custom scrapers
- 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
- 🛠️ Need another site, extra fields or a private build? Email abotapi@proton.me or message Telegram @abotapi.
- ⭐ Enjoying it? A quick review on the actor page helps other users find it.