Bayt Scraper - Middle East Jobs and Companies
Pricing
from $2.20 / 1,000 results
Bayt Scraper - Middle East Jobs and Companies
Extract Bayt.com jobs and company profiles across the Middle East and other Bayt markets. Get titles, salaries, locations, full descriptions and optional company details. Pay per delivered row plus a start fee.
Pricing
from $2.20 / 1,000 results
Rating
0.0
(0)
Developer
kane liu
Maintained by CommunityActor stats
1
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Security
Limited permissionsShare
Bayt Scraper
Extract Bayt.com jobs and company profiles across the Middle East and other Bayt markets as structured rows you can export.
- Job titles, employers, locations, salary ranges, career levels and posting dates.
- Full job descriptions, skills and employment details when requested.
- Company profiles, with optional websites, listed employees and open jobs.
- Countries and cities with job counts.
- Pay only for the rows you receive: $3.00 per 1,000 rows on the Free plan plus a small start fee.
What does Bayt Scraper do?
Bayt Scraper collects job and employer information from Bayt.com. Use it to compare hiring activity, track vacancies or build a shortlist of roles. Markets include the UAE, Saudi Arabia, Egypt, Qatar, Kuwait and other countries listed on Bayt; availability depends on the source.
- Job search: search with
keyword,country,cityand optional filters. - Job pages: supply
jobIdsto read specific jobs in full. - Company: supply
companyUrlfor one employer profile. - Locations: select
locationsto list countries, or a country's cities, with job counts. - All jobs: select
allJobsfor broader searches and continuation withcursor, subject to coverage and row limits. - Company open-job rows:
includeCompanyJobsis off by default. Each added job is a separate row, billed at the same price as the company row.
What data can you extract from Bayt?
Fields depend on the row type and what Bayt publishes. Missing values remain empty or null.
Job rows (dataType: job)
| Field | Description | Example |
|---|---|---|
jobId | Bayt job identifier | 5488783 |
title | Job title | Software Engineer |
listingUrl | Job page link | https://www.bayt.com/en/uae/jobs/software-engineer-5488783/ |
company | Employer name, unless confidential | Example Company |
companyUrl | Employer's Bayt page | https://www.bayt.com/en/company/al-futtaim-1661592/ |
location | Displayed job location | Dubai, UAE |
countryCode | Country code | AE |
salaryDisplay | Published salary range | AED 5,000 - 7,000 |
careerLevel | Career level | Mid Career |
experienceYears | Minimum and maximum experience | {"min": 2, "max": 5} |
workplace | Work arrangement | on-site |
postedAt | Posting timestamp | 2026-10-20T09:00:00+00:00 |
Full job rows (dataType: job_detail)
Full pages add these fields to job information where available. Reading a full page enriches the same row; it does not create a second billed row.
| Field | Description | Example |
|---|---|---|
description | Full job description as text | Develop and maintain applications. |
skills | Published skills and requirements | Python and SQL |
aiSummary | Summary supplied by Bayt, if present | null |
employmentType | Employment arrangement | Full Time Employee |
monthlySalaryRange | Salary text from the job page | null |
vacancies | Published vacancy count as text | 1 |
Company rows (dataType: company)
| Field | Description | Example |
|---|---|---|
name | Company name | Example Company |
groupId | Bayt employer identifier | 1661592 |
website | Website with includeCompanyPage | https://example.com |
about | Company introduction with includeCompanyPage | Example company description. |
employees | Up to 50 listed employees; part of the company row | [{"name": "Jane Doe", "title": "Recruiter", "profileUrl": null}] |
openJobs | Job count when includeCompanyJobs is enabled | 12 |
leadAbsences | Reasons contact fields are empty | {"geo": "Not on this site: Bayt gives no coordinates."} |
Location rows (dataType: location)
| Field | Description | Example |
|---|---|---|
type | Country or city | city |
name | Place name | Dubai |
locationId | Bayt location identifier | ae,4,0 |
jobsCount | Listed job count, not rows delivered | 120 |
jobsCountedAt | When the count was recorded | 2026-10-20T09:00:00+00:00 |
How to scrape Bayt
- Open Bayt Scraper in Apify Console. A free Apify account is enough to try it.
- Fill a target such as
keyword,jobIdsorcompanyUrl. - Set
maxResultsto5for a small first run. - Click Start and wait for completion.
- Download the dataset or read it through the Apify API.
Empty input {} starts an example search for software engineer in uae, limited to 3 rows. This is a normal priced run, not a free preview. The form prefills use the same example. Explicit jobs, locations and allJobs modes do not trigger the example just because their target fields are empty.
With mode set to auto, filling one target selects the matching mode. Job IDs take priority over a company; a company takes priority over a keyword or place. Check INPUT_REPORT for ignored fields and inferred choices.
Job search
Enter a title or skill in keyword. Add country before using city. In explicit jobs mode, an empty keyword means all jobs and an empty country means all countries. Enable enrichDetails for full pages.
Job pages
Put Bayt job IDs or job links in jobIds. Each available job produces one full job row. Closed or missing IDs can return no row. includeSimilarJobs adds related IDs inside each row, not separate job rows.
Company
Enter a Bayt company link or numeric ID in companyUrl. Enable includeCompanyPage for its website, about text, followers and listed employees. Enable includeCompanyJobs separately for job rows; with maxResults: 5, the company and its jobs share five rows.
Locations
Set mode to locations. Leave country empty for countries, or fill it for cities in that country. Check jobsCountedAt: some country counts were recorded earlier, rather than during this run.
All jobs
Set mode to allJobs, optionally narrowing by country or filters. When RUN_SUMMARY.nextCursor is present, send it as cursor in another run with the same search input. This mode can reach beyond one search's window, but does not guarantee every matching job.
What to fill in
| Field | What to enter | Default |
|---|---|---|
mode | auto, jobs, jobDetails, company, locations, allJobs | auto |
keyword | One job title, skill or company search | Empty; form sample software engineer |
country | Country name, code or slug such as uae | Empty; form sample uae |
city | City within the selected country | Empty |
jobIds | Array of Bayt job IDs or URLs | Empty |
companyUrl | Bayt company URL or numeric ID | Empty |
maxResults | Maximum rows per input | 70; form sample 3 |
dateInterval | Empty, 24h, 7d or 30d | Empty |
remote | Apply Bayt's remote-work filter | false |
careerLevel | Empty, student, graduate, entry, mid, management, director, executive | Empty |
employmentType | Empty, full time, part time, contractor, temporary, internship, freelance | Empty |
sortBy | relevance or date | relevance |
enrichDetails | Read full pages for matching jobs | false |
enrichLimit | Maximum job pages to enrich, from 0 to 300 | 30 |
includeSimilarJobs | Add similar IDs in jobDetails mode | false |
includeCompanyJobs | Add separately billed company job rows | false |
includeCompanyPage | Add public company-page attributes | false |
cursor | Earlier RUN_SUMMARY.nextCursor, for allJobs only | Empty |
Job search:
{"keyword": "accountant", "country": "uae", "city": "Dubai", "dateInterval": "7d", "maxResults": 5}
Job pages; replace the ID with a current job:
{"mode": "jobDetails", "jobIds": ["5488783"], "maxResults": 1}
Company and optional job rows:
{"companyUrl": "https://www.bayt.com/en/company/al-futtaim-1661592/", "includeCompanyJobs": true, "includeCompanyPage": true, "maxResults": 5}
Cities:
{"mode": "locations", "country": "uae", "maxResults": 5}
All-jobs mode with a small limit:
{"mode": "allJobs", "country": "india", "maxResults": 5}
maxItemsandlimitare accepted aliases formaxResults.- Unknown fields do not fail input resolution. Close misspellings can be corrected; others are ignored with a note. Invalid filter choices are ignored with a warning.
- Input-resolution errors use
INVALID_INPUT: <field> — <how to fix>. Further validation can return a plain field-specific message, such as requiring a Bayt company link. These checks happen before rows are collected or charged; the start fee is separate. INPUT_REPORTin the run's key-value store records fields filled, normalized, inferred or ignored, including whether the example ran.dateIntervalis relative to each run; it is not an automatically advancing date range.
Output example
Illustrative job row, shortened to the main fields; values are examples, not a freshly collected vacancy:
{"dataType": "job","type": "job","jobId": "5488783","name": "Software Engineer","title": "Software Engineer","company": "Example Company","location": "Dubai, UAE","country": "UAE","countryCode": "AE","salaryDisplay": null,"workplace": "on-site","status": "open","authority": "www.bayt.com","listingUrl": "https://www.bayt.com/en/uae/jobs/software-engineer-5488783/","phones": [],"emails": [],"contentDepth": "search"}
You can export the dataset as JSON, CSV, Excel, XML, RSS or an HTML table.
Why use this Bayt scraper?
- Pay per delivered row. Job, company and location rows have the same price.
- Optional detail without duplicate rows. Full job pages enrich existing rows; listed employees remain company attributes and are not billed separately.
- Useful partial results. If some job pages cannot be read, successfully read rows can still be returned with warnings. A hard stop before delivery is not guaranteed to preserve undelivered rows.
- Explainable empty fields. Missing salary and employer details are not invented;
leadAbsencesexplains unavailable contact information. - Several IDs per run.
jobIdsaccepts multiple jobs.keywordaccepts one search string, not separate keyword searches. - No proxy setup. You do not need to set up proxies, supply cookies or provide a Bayt account.
How much does it cost to scrape Bayt?
The Actor uses pay-per-event pricing. The start event costs $0.005, charged once per GB of run memory with a minimum of one event. At the default 512 MB, one start costs $0.005. Platform usage is included in these prices.
| Apify plan | Price per row | Price per 1,000 rows |
|---|---|---|
| Free | $0.0030 | $3.00 |
| Starter | $0.0030 | $3.00 |
| Scale | $0.0026 | $2.60 |
| Business | $0.0022 | $2.20 |
maxResults applies to each input: a search, company, location request or job ID/URL. Its default is 70, not a promise of 70 matches. Larger requests are collected in parts. All row types share the applicable allowance; adding company jobs does not add a separate allowance.
Free Apify plan runs are capped at 200 rows, with 10 runs of this Actor in total. Paid plans remove that run-count restriction, but row limits, source availability and your spending limit still apply. The whole run is capped by Maximum cost per run (maxTotalChargeUsd in the API).
Example: one search delivering 5 rows on the Free plan at 512 MB costs 5 × $0.003 + $0.005 = $0.020. A run with no rows has no row charge; it can still incur the start fee.
What happens when the run timeout is too short
Some Bayt collections, such as an allJobs run with a large maxResults, a search with enrichDetails: true or a company with includeCompanyJobs: true, can take longer than the run timeout you chose. In that case the run does not fail. It ends early with the status message "Queued on the collection backend; this run will resume automatically when results are ready (about N s)." and shows as ABORTED for a while.
When the results are ready, the same run starts again by itself, reports "Resumed: delivering N rows.", writes the rows to the same dataset and finishes as SUCCEEDED. Rows that were already delivered are skipped, so no row is delivered or charged twice. You do not need to start another run.
- This can happen at most 3 times per run. To avoid it, keep the default timeout of 3600 seconds.
- The synchronous API endpoints (
run-sync,run-sync-get-dataset-items) wait at most 300 seconds and can return an empty dataset while the run is paused. For larger jobs, start the run asynchronously and read the dataset after the run reaches SUCCEEDED, or use a webhook on the "succeeded" event.
Use with AI agents and the API
Apify MCP server (Claude, ChatGPT, Cursor, VS Code)
Add this Actor to a client that supports remote MCP servers:
https://mcp.apify.com?tools=lentic_clockss/bayt-scraper
Sign in with Apify through OAuth, or send Authorization: Bearer <YOUR_APIFY_TOKEN>. The tool returns run and dataset IDs; read rows with get-dataset-items. Clients without remote support can use npx @apify/actors-mcp-server --tools lentic_clockss/bayt-scraper with APIFY_TOKEN set.
Example prompt: "Find five accountant jobs in the UAE and return their titles, employers and links."
Apify API
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("lentic_clockss/bayt-scraper").call(run_input={"keyword": "accountant", "country": "uae", "maxResults": 5})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item)
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('lentic_clockss/bayt-scraper').call({keyword: 'accountant', country: 'uae', maxResults: 5});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items);
For HTTP, send the JSON input to POST https://api.apify.com/v2/acts/lentic_clockss~bayt-scraper/runs, with Authorization: Bearer <YOUR_APIFY_TOKEN>. After completion, read GET https://api.apify.com/v2/datasets/<datasetId>/items?format=json, using the run's defaultDatasetId.
Integrations
Use Apify integrations with Google Sheets, Make, Zapier, n8n, Slack or Airtable, or connect a webhook. Use Apify Schedules for recurring runs.
FAQ
Is it legal to scrape Bayt?
This Actor collects publicly available information. You are responsible for checking Bayt's terms and applicable data-protection law. Personal data needs a lawful basis for collection and use; public visibility alone does not settle that question.
Why did my run end as ABORTED?
Check the run log and status message to identify why it stopped, including whether it was manually aborted. Do not assume an aborted run delivered rows or will resume automatically. Inspect the dataset before starting another run.
How many results can I get?
The default is 70 rows per input. allJobs accepts up to 100,000; other modes cap maxResults at 5,000. Available matches, Free-plan limits and the maximum cost can reduce delivery. One job ID normally yields at most one job row.
Why are some fields empty?
Bayt may omit salary, hide an employer or provide no value. Description fields require full pages. Company websites and employees require includeCompanyPage; reading that page can fail without losing the basic company row.
Are phone numbers, email addresses and employees included?
Job and company rows return empty phones and emails. Public company pages can add up to 50 listed employees, with names, titles and profile links where shown. They are attributes, not separately billed rows or guaranteed contact details.
Why did I get no rows?
Check RUN_SUMMARY.emptyReason: LOCATION_UNRESOLVED means the place was not recognized; NO_MATCH can mean no matching jobs, an unknown company or closed job IDs. A successful empty run is different from a collection failure.
Can I continue a large search?
For allJobs, reuse RUN_SUMMARY.nextCursor with the same search input. A cursor may be omitted when the maximum charge prevented delivery of all returned rows. Changing the search makes the cursor unsuitable; start over without it.
Do I need a Bayt account?
No. The Actor accepts job-search inputs and public Bayt links without your Bayt login. It does not apply for jobs or access private candidate profiles.
Limitations
- One Bayt search can expose only its first 10,000 matches.
allJobswidens coverage, but some groups remain capped. UseRUN_SUMMARY.coveragerather than assuming a complete export. - Job counts and pages change. Continuation across runs can repeat rows; deduplicate saved exports by
jobId. - City filtering needs a country.
UKcovers the two country codes Bayt uses, but country availability is not a fixed market count. - Full descriptions, company-page attributes and similar-job IDs are optional and may be missing.
enrichLimitallows at most 300 full-page enrichments. - This documentation does not guarantee delivery of undelivered rows after a manual stop or timeout.
Related scrapers
More job board and freelance marketplace scrapers from the same publisher:
- LinkedIn Scraper
- Indeed Scraper
- Upwork Scraper
- Freelancer.com Scraper
- Glassdoor Scraper
- SEEK Scraper
- Fiverr Scraper
Browse all of our scrapers at apify.com/lentic_clockss.
Support
Found a problem or need another field? Open an issue in the Issues tab of this Actor's page and include the run ID and the input you used.