# Halal Certificate Checker: JAKIM & BPJPH (Malaysia, Indonesia) (`messnomore/halal-certificate-checker`) Actor

Bulk-verify halal certificates in the official Malaysia JAKIM and Indonesia BPJPH registries. Enter company, brand or product names or certificate numbers; get status (valid, expired, not found), expiry dates, certificate numbers and a fuzzy match confidence.

- **URL**: https://apify.com/messnomore/halal-certificate-checker.md
- **Developed by:** [Wong Xian Qi](https://apify.com/messnomore) (community)
- **Categories:** E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.50 / 1,000 certificate checks

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

### What does Halal Certificate Checker do?

**Halal Certificate Checker** verifies halal certification in bulk against the official public registries of
**Malaysia (JAKIM)** and **Indonesia (BPJPH)**. Paste a list of company names, brands, products or Indonesian
certificate numbers and get, for each one and each country, the **certificate status (valid, expired or not found),
expiry date, certificate number, certified company and a match confidence score**. Fuzzy matching handles spelling
variants and missing legal forms (Sdn Bhd, PT, Tbk), and on paid Apify plans an AI check rejects restaurants,
stalls and resellers that only use a brand name.

Data is read live from the [JAKIM halal directory (MYeHALAL)](https://www.halal.gov.my/) and the
[BPJPH halal certificate search (SIHALAL)](https://bpjph.halal.go.id/cari/sertifikat) at the time of your run.
Use it in Apify Console with no code, or as a **halal certificate verification API** from your own systems.

### Why use Halal Certificate Checker?

Checking suppliers one by one on two government websites, in Malay and Indonesian, with different search forms,
is slow and easy to get wrong. Halal Certificate Checker does it for you:

- ✅ **Bulk halal verification**: hundreds of suppliers, brands or products in one run, one row per query and country.
- 🇲🇾🇮🇩 **Two registries, one format**: JAKIM and BPJPH results in the same fields (status, dates, company, product).
- 🔎 **Fuzzy and AI-assisted matching**: "Gardenia Bakery KL" finds *GARDENIA BAKERIES (KL) SDN BHD*; a stall's
  "Indomie Goreng" is not mistaken for the Indomie brand owner.
- ⏰ **Expiry monitoring**: schedule a weekly run that returns only Malaysian certificates expiring soon, already
  expired or no longer listed.
- 🔗 **Verifiable**: every row links to the official registry page.
- 🤖 **Apify platform features**: run it on a schedule, call it by API, or send the results to Slack, email, Google
  Sheets, Make or Zapier with [integrations](https://docs.apify.com/platform/integrations).

Who uses it: **food importers and distributors**, **F\&B and retail procurement teams**, **halal compliance and QA
officers**, **marketplaces onboarding food sellers** and **export consultants** working with Malaysia and Indonesia.

### What data does the halal checker return?

| Field                            | Description                                                                                     |
| -------------------------------- | ----------------------------------------------------------------------------------------------- |
| `query`, `country`               | Your query and the registry country (`MY` or `ID`).                                             |
| `status`                         | `valid`, `expired` or `not_found` (`error` = registry lookup failed, not charged).              |
| `matchedCompany`                 | Certified company or business.                                                                  |
| `matchedProduct`, `matchedBrand` | Certified product and brand (or BPJPH trade name), when the match is a product.                 |
| `certificateNo`                  | BPJPH halal certificate number (JAKIM's public directory does not publish certificate numbers). |
| `issuingBody`                    | `JAKIM` or `BPJPH`.                                                                             |
| `validFrom`                      | Certificate issue date (BPJPH).                                                                 |
| `validUntil`, `daysToExpiry`     | Soonest upcoming expiry date and days left (JAKIM).                                             |
| `expiryDates`                    | All expiry dates listed for the matched company or product.                                     |
| `matchConfidence`                | 0–1 confidence that the registry entry is what you searched for.                                |
| `sourceUrl`                      | Official registry page to verify the result.                                                    |
| `checkedAt`                      | When the registry was checked.                                                                  |

Also included: `matchedOn` (company, brand, product or certificate number), `matchMethod` (string or AI), `recordType`,
`address` (registered companies only), up to 3 `alternatives` from other companies, a `note` with caveats and the
AI's one-line `aiReason`.

### How to check halal certificates in bulk

1. Click **Try for free** and open the **Input** tab.
2. Paste your **companies, brands, products or certificate numbers**, one per line.
3. Choose the **countries** (Malaysia, Indonesia or both) and, if you like, adjust the **match threshold**.
4. For expiry monitoring, set **only certificates expiring within (days)**, e.g. `60`.
5. Click **Start**. Each check takes a few seconds (the registries are queried politely, one request at a time);
   100 queries in both countries take about 10–15 minutes.
6. Open the **Output** tab and download the results as Excel, CSV or JSON, or filter by `status`.

### How much does halal certificate verification cost?

Halal Certificate Checker uses **pay-per-event pricing**, with no charge for compute time:

- **$0.005 per result** (one query checked in one country), including `not_found` results.
- **$0.002 per check** in expiry monitoring mode, whether or not the certificate needs attention.
- A start fee of $0.00005 per run.

Examples: 100 suppliers checked in Malaysia and Indonesia = 200 results = **$1.00**. A weekly monitoring run over
100 Malaysian suppliers = **$0.20**. Failed lookups (`error` rows) are never charged. **Maximum checks per run** is a
hard cap, and Apify also stops charging when your run reaches the maximum cost you set.

Apify's free plan includes monthly platform credit, which covers hundreds of checks. AI-assisted matching is
included on paid Apify plans at no extra cost.

### Input

See the **Input** tab for every option. Example input:

```json
{
    "queries": ["Gardenia Bakeries", "Mayora Indah", "ID31110081319591026", "Kapal Api"],
    "countries": ["MY", "ID"],
    "matchThreshold": 0.8,
    "useAi": true
}
```

- **queries**: company names work best. Brands and product names work too; Indonesian certificate numbers
  (`ID` followed by digits) are looked up exactly in BPJPH and skipped (not charged) for Malaysia.
- **matchThreshold**: minimum confidence to count as a match. Below it you get `not_found` plus the closest
  `alternatives`, so you can lower the threshold or refine the query.
- **onlyExpiringWithinDays**: turns on monitoring mode (Malaysia only, see FAQ).
- **maxChecks**: caps the number of checks, and so the cost, of one run.

### Output

You can download the dataset in various formats such as **JSON, HTML, CSV or Excel**. Example results (shortened):

```json
[
    {
        "query": "Gardenia Bakeries",
        "country": "MY",
        "status": "valid",
        "matchedCompany": "GARDENIA BAKERIES (KL) SDN BHD",
        "matchedProduct": null,
        "certificateNo": null,
        "issuingBody": "JAKIM",
        "validUntil": "2026-12-31",
        "daysToExpiry": 80,
        "expiryDates": ["2026-12-31", "2027-01-15", "2027-01-31", "..."],
        "matchConfidence": 0.97,
        "matchedOn": "company",
        "matchMethod": "string",
        "recordType": "company",
        "address": "LOT 3, JALAN PELABUR 23/1, SEKSYEN 23, 40300, SHAH ALAM, Selangor",
        "sourceUrl": "https://www.halal.gov.my/directory/slm_viewdetail.php?comp_code=COMP-20050727-143627&type=C&ty=CO",
        "alternatives": [
            {
                "company": "GARDENIA BAKERIES (EAST MALAYSIA) SDN. BHD.",
                "validUntil": "2027-05-15",
                "matchConfidence": 0.91
            }
        ],
        "note": "Company with several certificates: validUntil is the soonest upcoming expiry, see expiryDates.",
        "checkedAt": "2026-10-12T12:15:31.611Z"
    },
    {
        "query": "Kapal Api",
        "country": "ID",
        "status": "valid",
        "matchedCompany": "PT. SANTOS JAYA ABADI",
        "matchedProduct": "Kapal Api Café Latte",
        "matchedBrand": "Kapal Api, Good Day, ABC, Excelso",
        "certificateNo": "ID00410000056170720",
        "issuingBody": "BPJPH",
        "validFrom": "2026-08-31",
        "validUntil": null,
        "matchConfidence": 0.9,
        "matchedOn": "brand",
        "matchMethod": "ai",
        "sourceUrl": "https://bpjph.halal.go.id/cari/sertifikat?no_regis=ID00410000056170720",
        "note": "BPJPH certificates have no fixed expiry date: they stay valid while ingredients and production process are unchanged. validFrom is the issue date.",
        "aiReason": "PT. SANTOS JAYA ABADI is the Kapal Api brand owner/manufacturer in the registry.",
        "checkedAt": "2026-10-12T12:15:49.458Z"
    },
    {
        "query": "Mayora Indah",
        "country": "MY",
        "status": "not_found",
        "matchedCompany": null,
        "issuingBody": "JAKIM",
        "matchConfidence": null,
        "sourceUrl": "https://www.halal.gov.my/index.php?data=ZGlyZWN0b3J5L2luZGV4X2RpcmVjdG9yeTs7Ozs=",
        "alternatives": [],
        "checkedAt": "2026-10-12T12:15:31.784Z"
    }
]
```

### Use the halal certificate checker as an API

```bash
curl -X POST "https://api.apify.com/v2/acts/messnomore~halal-certificate-checker/run-sync-get-dataset-items" \
  -H "Authorization: Bearer YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"queries": ["Gardenia Bakeries", "Mayora Indah"], "countries": ["MY", "ID"]}'
```

See the **API** tab for clients in JavaScript and Python. For long lists, start the run asynchronously and read the
dataset when it finishes. You can also run it from AI assistants through the
[Apify MCP server](https://docs.apify.com/platform/integrations/mcp).

### Tips for better results

- **Indonesia: search by company name or certificate number.** BPJPH lists many food stalls whose menu items carry
  big brand names ("Indomie Goreng"), and its search shows the newest certificates first. "PT Indofood CBP" finds
  the manufacturer; "Indomie" alone may return `not_found` (the AI check rejects the stalls).
- **Malaysia: brand names work well** (JAKIM lists products with their brand), and company names find the
  company's full list of certificate expiry dates.
- **Use the full name of the company** when two companies share a word ("Gardenia Bakeries (KL)" vs "Gardenia Foods").
- **Check `alternatives`** on `not_found` rows: the right company may be just below your match threshold.
- **Monitoring**: schedule a weekly run with `onlyExpiringWithinDays` and an integration (email or Slack) to be
  warned before a supplier's certificate lapses.

### Related guides

- [How do you check a JAKIM or BPJPH halal certificate, and verify many suppliers at once?](https://wong13977-oss.github.io/halal-certificate-check/)

### FAQ

#### How does the matching work?

Each query is searched in the registry, then every returned entry is scored by how many of your words appear in
its company, brand or product name (spelling variants allowed) and how close the whole name is. Legal forms such
as Sdn Bhd, PT and Tbk are ignored. When the best match is only a brand or product name, or is close to the
threshold, the AI check (paid plans) looks at up to 5 different companies and picks the company itself, its
subsidiary, or the brand owner or official manufacturer, or none of them. `matchMethod` tells you which method
decided, and `aiReason` explains the AI's choice.

#### Which registries are covered? What about Singapore (MUIS)?

Malaysia's JAKIM halal directory (www.halal.gov.my, MYeHALAL) and Indonesia's BPJPH certificate search
(bpjph.halal.go.id, SIHALAL). Singapore's MUIS is **not** covered: its terms of use do not allow commercial reuse
of its directory without permission.

#### Why is validUntil empty for Indonesia?

Under Indonesian law as it stands (Law 6/2023 amending the Halal Product Assurance Law), a BPJPH halal certificate
stays valid from its issue date as long as the ingredients and production process do not change, so BPJPH
publishes no expiry date. You get the issue date in `validFrom`. For the same reason, expiry monitoring covers
Malaysia only.

#### Why does a Malaysian company show several expiry dates?

JAKIM certifies products and premises separately, so a company often holds many certificates. `validUntil` is the
soonest upcoming expiry and `expiryDates` lists them all. JAKIM's list view occasionally shows a date that its
detail page does not; we report the list as published.

#### What does "not_found" mean? Is the product not halal?

It means no entry in that registry matched your query above your match threshold. It does not mean the product is
haram: it may be certified under another company name, by another country's halal body, or not certified in that
country. Malaysia's public directory appears to drop certificates once they expire, so in monitoring mode a
certificate that disappears is returned as `not_found` for you to follow up.

The Actor reads the first page of each registry search. When a broad name has more results than that, the
`not_found` row says so in `note`: use the full company name, or the certificate number for Indonesia.

#### How fresh is the data?

Live: every run reads the registries at that moment. Each row has `checkedAt`.

#### Why did I get fewer rows than queries × countries?

Indonesian certificate numbers are skipped for Malaysia (JAKIM cannot search them), monitoring mode returns only
rows that need attention, and runs stop at **Maximum checks per run** or your maximum cost per run.

#### What if a registry is down?

The affected rows get `status: "error"` and are not charged. After three failures in a row the Actor pauses for a
minute and tries again; after two such pauses it stops querying that registry for the rest of the run. Run those
queries again later.

#### Is this an official halal certificate verification?

No. Halal Certificate Checker is not affiliated with or endorsed by JAKIM or BPJPH. It reads their public search
pages and reports what they show; for audits or legal purposes, confirm on the official page in `sourceUrl`. AI
checks can be wrong, which is why each row shows its confidence and reason.

#### Is my input stored or shared?

On paid plans, your query and the candidate registry entries are sent to the OpenAI API only to decide ambiguous
matches; the Actor does not write your queries to its logs. Like every Apify run, your input and results stay in
your own run storage, which you can delete at any time.

#### Is it legal to check halal certificates this way?

The Actor reads only public registry search pages, one request at a time, and returns the business details those
registries publish for verification. It does not open pages with personal details of registry staff. Our Actors are
ethical and do not extract any private user data, such as email addresses, gender, or location. They only extract
what the user has chosen to share publicly. We therefore believe that our Actors, when used for ethical purposes by
Apify users, are safe. However, you should be aware that your results could contain personal data: in Indonesia,
many small businesses are registered under the owner's personal name. Personal data is protected by the GDPR in the
European Union and by other regulations around the world. You should not scrape personal data unless you have a
legitimate reason to do so. If you're unsure whether your reason is legitimate, consult your lawyers.

#### I found wrong or missing data. What can I do?

Open the **Issues** tab and include the query, the country and the `sourceUrl`. Feedback and feature requests are
welcome there too.

# Actor input Schema

## `queries` (type: `array`):

One entry per line, e.g. "Gardenia Bakeries", "Mayora Indah", "Old Town White Coffee" or an Indonesian certificate number such as "ID31110081319591026". Spelling variants and missing legal forms (Sdn Bhd, PT, Tbk) are fine. Each entry is checked in every selected country. Duplicates are removed.

## `countries` (type: `array`):

Registries to check: Malaysia (JAKIM / MYeHALAL directory) and Indonesia (BPJPH / SIHALAL certificate search). Each query × country is one result. Indonesian certificate numbers (ID…) are only checked in Indonesia: Malaysia skips them without a row or a charge.

## `matchThreshold` (type: `number`):

Minimum match confidence (0 to 1) for a registry entry to count as your query. Lower it to accept looser name matches; raise it for stricter ones. Below the threshold the result is "not_found" with the closest alternatives listed.

## `useAi` (type: `boolean`):

On paid Apify plans, an AI model double-checks ambiguous matches (brand or product names, near misses) and rejects resellers, restaurants and stalls that only use the brand. Free plans always use string matching.

## `onlyExpiringWithinDays` (type: `integer`):

Turns on monitoring mode (Malaysia only, since Indonesian certificates have no expiry date): every query is checked, but only certificates that expire within this many days, have already expired or are no longer listed are returned. Billed per check at the lower monitoring price. Leave empty for a normal check.

## `maxChecks` (type: `integer`):

Stops after this many query × country checks (caps the cost of a run). Failed lookups are not counted or charged.

## Actor input object example

```json
{
  "queries": [
    "Gardenia Bakeries",
    "Mayora Indah",
    "ID31110081319591026"
  ],
  "countries": [
    "MY",
    "ID"
  ],
  "matchThreshold": 0.8,
  "useAi": true,
  "maxChecks": 1000
}
```

# Actor output Schema

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

No description

## `summary` (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 = {
    "queries": [
        "Gardenia Bakeries",
        "Mayora Indah",
        "ID31110081319591026"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("messnomore/halal-certificate-checker").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 = { "queries": [
        "Gardenia Bakeries",
        "Mayora Indah",
        "ID31110081319591026",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("messnomore/halal-certificate-checker").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 '{
  "queries": [
    "Gardenia Bakeries",
    "Mayora Indah",
    "ID31110081319591026"
  ]
}' |
apify call messnomore/halal-certificate-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,messnomore/halal-certificate-checker"
        }
    }
}
```

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/9AqjoKWPFQ9BnAueP/builds/68sEHo2HgeBzq39FV/openapi.json
