# UAE Manufacturers Directory Scraper - MOIAT Factories & Emails (`scrapersdelight/uae-manufacturers-directory-scraper`) Actor

From $0.40 per 1,000 rows. Scrape the UAE's official MOIAT industrial register: 3,486 licensed factories with 100% e-mail and phone fill, emirate, 10,309 HS-coded products and 5,900 ISIC activities. Filter by emirate, HS chapter or ISIC code - including the 92-factory automotive cut.

- **URL**: https://apify.com/scrapersdelight/uae-manufacturers-directory-scraper.md
- **Developed by:** [Scrapers Delight](https://apify.com/scrapersdelight) (community)
- **Categories:** Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.40 / 1,000 per factory returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#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

## UAE Manufacturers Directory Scraper

Turns the UAE Ministry of Industry and Advanced Technology's **industrial licence register** into a
clean B2B lead list of licensed manufacturers — **3,486 factories, every one with an e-mail address
and a phone number** — with each factory's HS-coded products and ISIC activities nested in the row.

The source is MOIAT's own open-data export (`il.moiat.gov.ae/en/OpenData`), the register every
factory operating legally in the UAE appears in.

***

### What one row looks like

```json
{
  "recordId": "8f2c1a9be40d7d31",
  "factoryNameEn": "AL BUSTAN ADHESIVES MANUFACTURING/L.L.C",
  "factoryNameAr": "البستان لصناعة مواد الصق/ذ.م.م",
  "emirate": "Ajman",
  "email": "albustanuae@gmail.com",
  "phone": "052-8785058",
  "phoneE164": "+971528785058",
  "productCount": 3,
  "activityCount": 1,
  "products": [
    { "hsCode": "39123900", "descriptionEn": "  - - Other", "descriptionAr": "ـ ـ غيرها" }
  ],
  "activities": [
    { "isic4Code": "2029006", "activityEn": "Glues and Prepared Adhesives Manufacturing",
      "activityAr": "صناعة الأصماغ والمواد اللاصقة المحضَّرة" }
  ],
  "sourceUrl": "https://il.moiat.gov.ae/en/OpenData/ExporttoXML",
  "scrapedAt": "2026-09-11T06:41:02.118Z"
}
```

| field | what it is |
|---|---|
| `recordId` | Stable id for the factory — see **There is no licence number** below |
| `factoryNameEn` · `factoryNameAr` | Registered factory name, both languages as MOIAT publishes them |
| `emirate` | One of the seven emirates |
| `email` · `phone` | Contact details as filed with MOIAT |
| `phoneE164` | `phone` normalised to +971…, or `null` where the filed number cannot be resolved |
| `productCount` · `activityCount` | How many products / activities this factory declares |
| `products[]` | The factory's declared products: HS code plus description in English and Arabic |
| `activities[]` | ISIC Rev.4 activity codes with English and Arabic labels |

### Measured field fill

Measured on the complete register, 2026-09-11 — the whole register, not a sample:

| field | fill |
|---|---|
| `factoryNameEn`, `factoryNameAr`, `emirate`, `email`, `phone` | **100%** (3,486 / 3,486) |
| `phoneE164` | 99.5% (3,467) — the remainder are filed numbers too short or too long to resolve |
| `products[]` | 100% have at least one — 10,309 product rows, mean 3.0, max 172 |
| `activities[]` | 100% have at least one — 5,900 activity rows, mean 1.7, max 23 |

| emirate | factories |
|---|---|
| Dubai | 1,321 |
| Sharjah | 596 |
| Ajman | 435 |
| Umm Al Quwain | 424 |
| Abu Dhabi | 400 |
| Ras Al Khaimah | 257 |
| Fujairah | 53 |

### Input

| input | default | what it does |
|---|---|---|
| `emirate` | all seven | Keep only factories in the selected emirates |
| `hsChapter` | — | Keep factories making a product whose HS code starts with one of these 4-digit headings |
| `isic4Code` | — | Keep factories carrying one of these exact ISIC4 activity codes |
| `requireEmail` | `false` | Keep only factories with an e-mail (today that is all of them — see below) |
| `maxRecords` | `0` (all) | Hard cap on delivered, and therefore charged, rows |
| `proxyConfiguration` | Apify Proxy **RESIDENTIAL** | See **Why residential** below |

Every filter selects **factories**. Products and activities stay nested inside the factory row, so
one delivered row is always one factory — a factory with 172 products costs the same as one with a
single product.

#### The automotive cut

The register is a general industrial one, but it contains a usable automotive segment. Filtering
`hsChapter` to `8708, 4011, 4012, 8507, 3403, 8409, 8716, 8511, 8512, 8482, 4013, 8714` selects
**92 factories** — auto parts, tyres, batteries, lubricants, trailers, lighting and bearings.
That is the honest strict-chapter count. Adding HS `2710` (petroleum oils) brings in 97 more, but
those are only partly automotive, so they are left out of the preset rather than padding it.

### Honest limits

**There is no licence number.** This is a licence register whose public export does not publish the
licence number. It also carries **no street address** (emirate only), **no website**, **no capital**
and **no employee count** — those fields exist behind MOIAT's login, not on the open-data surface.
`recordId` is therefore a value we compute: a stable hash of name (both languages), phone, e-mail and
emirate. It is stable across runs as long as MOIAT does not edit those fields, and it is **not** a
MOIAT identifier — do not send it to MOIAT expecting them to recognise it.

**Rows are not the same as distinct contacts.** About 7.5% of rows share an e-mail address with
another row in the same run, because UAE group companies register several factories under one
address — `ayman@alshirawi.ae` covers 16 factories, `commercialdep@hassani.ae` 12, `tl@iffco.com` 8.
Those are genuinely separate licensed factories, so they are separate rows, but if you are counting
mailboxes rather than factories the run summary gives you `distinctEmails` (3,225 on the full
register) alongside the row count.

**Two factories are invisible.** The report's own header declares 3,488 factory rows; the export
renders 3,486. Two pairs are identical on every published field — same name in both languages, same
phone, same e-mail, same emirate — so the source's own grouping merges them before we ever see them.
They are unrecoverable from this surface, and we would rather say so than quietly report 3,488.

**The register moves.** Repeat pulls on the same day returned 3,484, 3,485 and 3,486 factories. The
Actor asserts a **floor**, never an exact count, and fails a run that comes back below it.

### Why residential

`il.moiat.gov.ae` serves the whole register as one 6.3 MB download. Measured 2026-09-11, six pulls
through the Apify **datacenter** proxy: three arrived complete, and **three were cut off mid-file**
(one at 1.76 MB, one at 0.41 MB of an expected 6.34 MB). Three residential pulls were all complete,
and faster — 16–19 s against 25–44 s.

That failure is dangerous precisely because it does not look like a failure: the request returns
HTTP 200 with an XML content type, and a tolerant parser will happily read a half-file and hand back
a 3.7%-complete register. So before anything is parsed, delivered or charged, the Actor checks that
the received byte count matches the server's own `Content-Length` **and** that the document ends with
its closing tag, parses strictly, and requires the factory count to clear a floor. If any of those
fail it retries on a fresh proxy session up to three times and then **fails the run** — it will not
deliver a partial register, and a failed run charges nothing.

### Pricing

Pay per event: **$0.0004 per `factory-record`** — charged only for a factory row actually delivered
to your dataset. Nested products and activities are never billed separately. Rows dropped by a
filter are never delivered and never charged, and a run that returns nothing costs nothing.

The complete register of 3,486 factories is about **$1.39**; the 92-factory automotive cut is **$0.04**.

Delivery is budget-aware: rows are delivered and charged together in chunks, so a run capped by your
budget stops cleanly at the cap instead of delivering rows it cannot bill for.

Every run also writes a `RUN_SUMMARY` record to the key-value store with the factory count against
the register's own declared count, product and activity row totals, what each filter dropped,
delivered vs charged, the distinct-e-mail count, and how many download attempts were needed.

### Legal

MOIAT publishes this register as **open data**, through an export button on a public page, with no
login, no API key and no robots.txt on the host. The contact details are the ones each factory filed
for its industrial licence. You are responsible for how you use them — for outreach into the UAE
that means the UAE's own e-marketing rules under the Consumer Protection Law, and the equivalent
wherever you are sending from.

# Actor input Schema

## `emirate` (type: `array`):

Keep only factories in these emirates. Leave empty for all seven. Measured counts on 2026-09-11: Dubai 1,321 · Sharjah 596 · Ajman 435 · Umm Al Quwain 424 · Abu Dhabi 400 · Ras Al Khaimah 257 · Fujairah 53.

## `hsChapter` (type: `array`):

Keep only factories that make at least one product whose HS code starts with one of these 4-digit headings. Example — the automotive cut is 8708, 4011, 4012, 8507, 3403, 8409, 8716, 8511, 8512, 8482, 4013, 8714, which selects 92 factories. The register holds 3,977 distinct HS codes.

## `isic4Code` (type: `array`):

Keep only factories carrying one of these ISIC4 activity codes (exact match). MOIAT publishes 5,900 activity rows across the register.

## `requireEmail` (type: `boolean`):

The register currently carries an e-mail on 100% of factories, so this changes nothing today. It is here so a run cannot start silently delivering contactless rows if MOIAT's fill rate drops.

## `maxRecords` (type: `integer`):

Hard cap on delivered — and therefore charged — rows. 0 means the whole matching set. The complete register is about 3,486 factories.

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

Apify Proxy, RESIDENTIAL. Measured 2026-09-11: 3 of 6 datacenter pulls were cut off mid-file, residential was 3 of 3 clean and faster. The Actor detects a truncated download and fails the run rather than delivering a partial register, but residential avoids the retries.

## Actor input object example

```json
{
  "emirate": [],
  "hsChapter": [],
  "isic4Code": [],
  "requireEmail": false,
  "maxRecords": 0,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `items` (type: `string`):

One row per factory in the MOIAT industrial register - name in English and Arabic, emirate, e-mail, phone (raw and E.164), plus the factory's HS-coded products and ISIC activities nested inside the row. One row is always one factory, so the row count is the charge count.

## `runSummary` (type: `string`):

RUN\_SUMMARY: factories parsed vs the count the report states in its own header, product and activity row totals, what each filter dropped, delivered vs charged, how many delivered rows share an e-mail with another row, and how many download attempts were needed.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapersdelight/uae-manufacturers-directory-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("scrapersdelight/uae-manufacturers-directory-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 '{}' |
apify call scrapersdelight/uae-manufacturers-directory-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapersdelight/uae-manufacturers-directory-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/qD2RklNOxc6oAa4vw/builds/YSgXyOxZPiSzpfFmf/openapi.json
