# Bayt Scraper - Middle East Jobs, Salaries & Companies (`scrapewise/bayt-scraper`) Actor

Scrape bayt.com jobs in the UAE, Saudi Arabia, Qatar, Kuwait, Egypt and 11 more countries by keyword, city, date, career level and contract: title, company, size, industry, salary, experience, education, skills, full description. Schedule it with onlyNew for alerts. Error rows are free.

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

## Pricing

from $0.85 / 1,000 job delivereds

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/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

## Bayt Scraper: Middle East jobs with salaries, companies and full descriptions

Bayt Scraper collects **job listings from bayt.com**, the largest job board of the Middle East and North Africa,
without an account, cookies or a browser. Search by keyword in the UAE, Saudi Arabia, Qatar, Kuwait, Oman, Bahrain,
Egypt, Jordan and eight more countries, narrow it down by city, date, career level, contract and employer type, or
paste any bayt.com search link. Each job comes back as one clean row: title, company with size and industry, city and
country, contract, experience, education, salary range when the employer publishes it, skills, preferred candidate
profile, posted and closing dates, and the full description in text and HTML.

It is used for salary and hiring research in the Gulf, for job aggregators and alert services, for recruitment
agencies watching which companies are hiring, and for labor market dashboards across the GCC and North Africa.

### At a glance

| What | Price |
|---|---|
| Job delivered | **US$ 1.00 per 1,000 jobs** (US$ 0.001 each) |
| Run start | US$ 0.005 per run |

- 500 accountant jobs in the UAE with full details = **US$ 0.505**.
- Error rows, duplicates and jobs skipped by `onlyNew` are never charged. `maxItems` is a hard cap, and a spending
  limit set on the run stops it cleanly with everything delivered so far.
- Runs on the Apify datacenter proxy, which bayt.com accepts. No residential proxy cost in the normal case.

### Quick start

```json
{
  "searchQueries": ["accountant"],
  "country": "uae",
  "maxItems": 50
}
```

Sales jobs in two Saudi cities, full time, posted in the last 30 days:

```json
{
  "searchQueries": ["sales"],
  "country": "saudi-arabia",
  "cities": ["Riyadh", "Jeddah"],
  "postedWithin": "30d",
  "employmentTypes": ["Full time"],
  "maxItems": 200
}
```

A search link copied from the site, used as it is (every filter in the link is kept):

```json
{
  "startUrls": ["https://www.bayt.com/en/qatar/jobs/civil-engineer-jobs/"],
  "maxItems": 100
}
```

Single job pages work too: paste links like `https://www.bayt.com/en/uae/jobs/<job-title>-<id>/`.

### Input

| Field | What it does |
|---|---|
| `searchQueries` | Job titles or keywords, one per line. Each keyword is one search. Empty with no links = every job of the country (or city). |
| `country` | UAE by default. Also Saudi Arabia, Qatar, Kuwait, Oman, Bahrain, Egypt, Jordan, Lebanon, Iraq, Morocco, Algeria, Tunisia, Libya, Pakistan, India, or `international` for all countries at once. |
| `cities` | Optional cities inside the country, such as Dubai, Abu Dhabi, Riyadh, Jeddah, Doha or Cairo. Each city is searched for every keyword. |
| `postedWithin` | `any`, `24h`, `7d` or `30d`, the site's own "Date posted" filter. |
| `careerLevels` | Student/Internship, Fresh graduate, Entry level, Mid career, Management, Director/Head, Senior executive. |
| `employmentTypes` | Full time, Part time, Contractor, Freelance, Internship, Temporary. |
| `companyTypes` | Employer (private sector), Employer (public sector), Recruitment agency, Non-profit organization. |
| `remoteOnly` | Only jobs marked as work from home. |
| `easyApplyOnly` | Only jobs that take applications directly on bayt.com. |
| `startUrls` | bayt.com search links (with any filter set on the site) or single job links. |
| `includeDetails` | On by default: opens each job page for description, skills, salary, education, preferred candidate, company size and industry. Off: faster, search card fields only. |
| `maxItems` | Cap for the whole run, across all searches (default 50; 0 = no cap). |
| `onlyNew` | Remembers what earlier runs of the same search delivered and returns only new jobs. Built for schedules. |
| `proxyConfiguration` | Apify datacenter proxy by default. |

Several values inside one filter add up (OR), and different filters narrow each other (AND), exactly like on the site.

### Output

One row per job. Fields that bayt.com does not give for a job are `null`; nothing is invented.

| Field | Description |
|---|---|
| `jobId` | bayt.com job id |
| `title` | Job title as published |
| `companyName`, `companyId`, `companyUrl`, `companyLogo` | Employer name, bayt.com company id, company page and logo |
| `companySize`, `companyIndustry` | Employee range (for example 50-99) and industry, when the employer has a profile |
| `location`, `city`, `region`, `country`, `countryCode` | Location as shown on the card, plus the structured address (ISO country code) |
| `employmentType` | FULL_TIME, PART_TIME, CONTRACTOR, TEMPORARY, INTERN... |
| `employmentSummary`, `experience` | Contract, career level and experience line as the site shows it |
| `minExperienceYears` | Minimum experience in years, when the job sets one |
| `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod` | Salary range when published (about 4 in 10 jobs in our tests) |
| `education` | Required degree category, when set |
| `openings` | Number of open positions, when set |
| `nationalityRestriction` | For example "Saudi nationals" or "UAE nationals" when the job is limited to citizens |
| `preferredCandidate` | The site's "Preferred candidate" block: years of experience, degree, career level, residence, nationality... |
| `isRemote` | `true` for work from home jobs (set when the search uses the remote filter or the job says so) |
| `summary` | The short summary bayt.com shows on the search card |
| `skills` | The "Skills" section of the job page |
| `description`, `descriptionHtml` | Full description, as plain text and as the original HTML |
| `postedAt`, `postedAgo`, `datePosted`, `validThrough` | Exact posting time, the "x days ago" label, posting date and closing date |
| `easyApply`, `directApply` | Whether the job takes applications on bayt.com |
| `isAggregated` | `true` for jobs bayt.com collected from other sources |
| `url` | Job page on bayt.com |
| `sourceQuery` | The keyword, city or link that found the job |
| `scrapedAt`, `errorCode`, `error` | Collection time; error fields are `null` on job rows |

#### Example (real row, shortened texts)

```json
{
  "type": "job",
  "jobId": "5495705",
  "title": "Sales Consultant",
  "companyId": "2322959",
  "companyLogo": "https://secure.b8cdn.com/70x70/images/logo/59/2322959_logo_1792140474_n.png",
  "companySize": "50-99",
  "companyIndustry": "Perfume & Cosmetics",
  "city": "As Sulaymaniyah",
  "region": "Riyadh",
  "country": "Saudi Arabia",
  "countryCode": "SA",
  "employmentType": "FULL_TIME",
  "employmentSummary": "Full time · Mid career · 1 - 10 Years of Experience",
  "minExperienceYears": 1.0,
  "salaryMin": 1500,
  "salaryMax": 2000,
  "salaryCurrency": "USD",
  "salaryPeriod": "month",
  "education": "high school",
  "openings": 10,
  "preferredCandidate": {
    "Years of experience": "1 - 10 years",
    "Degree": "High school or equivalent",
    "Career level": "Mid career"
  },
  "summary": "Elevate your career in sales consulting with a focus on luxury products...",
  "skills": "- Previous experience in luxury product sales or beauty products.\n- Good knowledge of luxury products and global brands...",
  "description": "Responsibilities and Duties\n- Welcome clients and provide a refined and professional shopping experience...",
  "postedAt": "2026-10-16T18:56:26Z",
  "postedAgo": "5 hours ago",
  "datePosted": "2026-10-16",
  "validThrough": "2026-11-15T00:00:00Z",
  "easyApply": true,
  "directApply": true,
  "isAggregated": false,
  "sourceQuery": "sales in Riyadh (saudi-arabia)",
  "errorCode": null,
  "error": null
}
```

Company names keep the language the employer used (Arabic names stay in Arabic). Job texts come in English when
bayt.com offers the English version.

### Errors you may see

Error rows have `type: "error"`, an `errorCode` and a plain message. They are **never charged**.

| errorCode | Meaning | What to do |
|---|---|---|
| `INVALID_INPUT` | A filter value is not one of the allowed options | Use the options listed in the input form |
| `INVALID_URL` | The link is not a bayt.com search or job link | Copy the link from the address bar on bayt.com |
| `NO_RESULTS` | bayt.com has no job for that search and filters | Use fewer filters, another country or a broader keyword |
| `NOT_FOUND` | A job link is no longer online | Jobs close; search again for current ones |
| `BLOCKED` | bayt.com refused every attempt for a search | Run again in a few minutes |
| `UNEXPECTED` | Anything else; the run still ends cleanly | Run again; if it repeats, open an issue with the run link |

### Integrations, scheduling and AI agents

- **Schedule** a daily run with `onlyNew` on in [Apify schedules](https://docs.apify.com/platform/schedules) to get
  only the jobs posted since the last run, for alerts or a hiring tracker.
- **Export** as JSON, CSV, Excel or XML, or read the dataset from the [Apify API](https://docs.apify.com/api/v2).
- **Connect** it to Make, n8n, Zapier or Google Sheets through
  [Apify integrations](https://docs.apify.com/platform/integrations), for example to post new Dubai jobs to Slack.
- **AI agents:** call it as a tool through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp)
  in Claude, ChatGPT, Cursor or any MCP client, for example "list 100 data analyst jobs in Riyadh posted this week and
  summarize the salary ranges".

### FAQ

**Do I need a bayt.com account?** No. The Actor reads the same public pages any visitor sees.

**How many jobs can I get?** As many as bayt.com lists for the search. A broad search such as all jobs in the UAE has
thousands; the site shows 30 per page and the Actor walks the pages until the end or until `maxItems`.

**How fast is it?** About 50 jobs with full details in 10 to 15 seconds in our tests. With `includeDetails` off it is
several times faster, since one page brings 30 jobs.

**Why is the salary empty on some jobs?** Many employers in the region do not publish a salary. When bayt.com shows a
range, it is in `salaryMin`, `salaryMax`, `salaryCurrency` and `salaryPeriod`.

**Can I search in Arabic?** Yes, Arabic keywords work. Results come from the English version of the site.

**Is personal data included?** No. The Actor returns job and company data only. No recruiter names, and e-mail
addresses or phone numbers written inside job texts are replaced with `[contact removed]`.

**What does `onlyNew` remember?** Job ids per search (keyword, country, city and filters), stored in a key-value
store in your own Apify account. Change any filter and it counts as a new search.

### Limitations

- The site shows up to about 10,000 jobs for one search; split very broad searches by city or filter.
- `companySize`, `companyIndustry`, `education`, `openings` and salary only exist when the employer fills them in.
- Jobs that bayt.com collects from other sources (`isAggregated: true`) have no company page and fewer details.
- `cities` must be spelled as on bayt.com in English (Dubai, Abu Dhabi, Riyadh, Al Khobar...).

### Changelog

- **16 Oct 2026**: first version. Keyword, country, city, date, career level, contract, employer type, remote and Easy
  Apply filters; search and job links; full details with salary, skills and preferred candidate; `onlyNew` for
  schedules; free error rows.

# Actor input Schema

## `searchQueries` (type: `array`):

Job titles or keywords, one per line, for example accountant or software engineer. Each keyword is one search. Leave empty to list every job of the country or city, or when you paste links below.

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

Country to search in, as bayt.com splits its listings.

## `cities` (type: `array`):

Optional cities inside the country, one per line, for example Dubai, Abu Dhabi, Riyadh or Jeddah. Each city is a separate search for every keyword. Empty = the whole country.

## `postedWithin` (type: `string`):

Only jobs posted or refreshed in this window, the same filter as the site.

## `careerLevels` (type: `array`):

Keep only these career levels, as bayt.com classifies them. Empty = all.

## `employmentTypes` (type: `array`):

Keep only these contract types. Empty = all.

## `companyTypes` (type: `array`):

Keep only jobs posted by these kinds of employers. Empty = all.

## `remoteOnly` (type: `boolean`):

On: only jobs bayt.com marks as work from home.

## `easyApplyOnly` (type: `boolean`):

On: only jobs that take applications directly on bayt.com.

## `startUrls` (type: `array`):

Optional: bayt.com search links copied from the address bar after setting filters on the site (used as they are), or links to single job pages.

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

On: opens each job page for the full description, skills, salary (when published), education, preferred candidate, company size and industry. Off: faster, only the search card fields.

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

Hard cap for the whole run, across all searches. 0 = no cap.

## `onlyNew` (type: `boolean`):

On: remembers the jobs delivered in earlier runs of the same search (in your account) and delivers only jobs not seen before. Skipped jobs are free.

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

Apify datacenter proxy by default, which bayt.com accepts. Change it only if you know you need to.

## Actor input object example

```json
{
  "searchQueries": [
    "software engineer"
  ],
  "country": "uae",
  "postedWithin": "any",
  "remoteOnly": false,
  "easyApplyOnly": false,
  "includeDetails": true,
  "maxItems": 50,
  "onlyNew": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `resultsCsv` (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 = {
    "searchQueries": [
        "software engineer"
    ],
    "maxItems": 50,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapewise/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 = {
    "searchQueries": ["software engineer"],
    "maxItems": 50,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapewise/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 '{
  "searchQueries": [
    "software engineer"
  ],
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call scrapewise/bayt-scraper --silent --output-dataset

```

## MCP server setup

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