# OCC Mundial Jobs Scraper (`normdata/occ-scraper`) Actor

Every job on OCC Mundial, Mexico's biggest job board, in one run: salary ranges in MXN, category, contract, work model, education, benefits, skills and full descriptions. Recruiters, HR teams and analysts get 1,000 jobs in under a minute.

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

## Pricing

from $10.00 / 1,000 jobs

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

![Norm Data](https://raw.githubusercontent.com/FabriAV/normdata/refs/heads/main/assets/banner_norm2.png)

## 💼 OCC Mundial Jobs Scraper

Extract job listings from **OCC Mundial**, Mexico's biggest job board: title, company, salary (as shown and as numbers in MXN), city, state, category, contract, schedule, work model, education, benefits, skills, screening questions and the full description. Search by keyword, state or city, and filter by category, work model, contract, education, salary range and posting date. About **1,000 jobs with full details in under a minute**.

OCC lists more than 55,000 open jobs. The site itself stops paging a search at about 10,000 results; this Actor splits bigger searches by category and state, so a run with no filters can return the whole board.

### 🎯 Who uses it?

#### 🧑‍💼 Recruiters and staffing agencies

See who is hiring for a role, in which city and at what salary, and spot companies hiring many people at once.

#### 💰 HR and compensation teams

Benchmark pay by job title, category, state and contract with real published salaries, already parsed into numbers with the pay period.

#### 📈 Labor market analysts and journalists

Track demand by category, work model (remote, hybrid, on-site), education level and contract type across Mexico, on a schedule.

#### 🛠️ Job board and HR tech builders

Feed an aggregator, alert service or matching model with fresh, structured Mexican jobs, including skills and benefits.

### ✨ What it does

- **Search** by one or more keywords, in one or more states or cities, or across all of Mexico.
- **Every OCC filter as a real input:** category (23), work model, contract type, education level, minimum and maximum salary, posting date, and sort order.
- **No result cap:** searches over 10,000 jobs are split automatically, so nothing is cut off.
- **Full details on every row:** full description, benefits, required skills, screening questions, schedule, education, posting and expiry dates.
- **Salary as numbers:** "$15,000 - $18,000 Mensual" becomes `salaryMin`, `salaryMax`, `salaryCurrency` and `salaryPeriod`. Hidden salaries stay empty instead of guessed.
- **Paste a search link:** reuse a search you already filtered on occ.com.mx.

### 🏆 Why this scraper

- **Fast without shortcuts.** About 1,000 jobs with full details in under a minute (14 seconds in our tests), with no browser and no proxy.
- **Every filter, not just a keyword box.** Category, work model, contract, education, salary and date are inputs you pick from a list.
- **The whole board when you need it.** Big searches are split into pieces OCC can page through completely, newest first, with no duplicates.
- **Honest about what OCC shows.** Confidential companies stay confidential (`company` is empty and `confidentialCompany` is true). Recruiter names, phones and emails are never collected.

### ⚖️ How it compares

| Capability | This actor | [unfenced-group](https://apify.com/unfenced-group/occ-com-mx-scraper) | [corvuslab](https://apify.com/corvuslab/occ-mundial-jobs-scraper) | [gio21](https://apify.com/gio21/occmundial-jobs-scraper) | [stilled_stalagmite](https://apify.com/stilled_stalagmite/occ-mexico-jobs-scraper) |
|---|:--:|:--:|:--:|:--:|:--:|
| Several keywords and locations in one run | **yes** | no | no | no | no |
| Category filter | **several** | one | no | no | no |
| Work model, education, salary filters | **yes** | no | no | no | no |
| Contract filter | **several** | one | no | no | no |
| Posting date filter and newest-first sort | **yes** | no | no | no | no |
| Past OCC's 10,000-job paging limit | **yes** | no | no | no | no |
| Full description | **yes** | optional | yes | yes | yes |
| Skills and screening questions | **yes** | no | no | no | no |
| Benefits list | **yes** | no | no | no | no |
| Salary min/max numbers and pay period | **yes** | yes | partial | no | no |
| Proxy | **none needed** | not stated | not stated | not stated | not stated |

corvuslab adds incremental mode and Telegram, Slack or Discord alerts, and corvuslab and unfenced-group can return the description as HTML or markdown. Here the description is clean plain text with bullet points kept.

### 📦 What data you get

| Field | Description |
| --- | --- |
| `jobId`, `url` | OCC's job ID and the job page. |
| `title`, `company`, `confidentialCompany`, `verifiedCompany` | Job title and hiring company; confidential listings have no company name. Verified means OCC checked the employer. |
| `city`, `state` | Where the job is. |
| `salary`, `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod` | The salary exactly as shown, the same as numbers in MXN, and the period (monthly, biweekly, weekly, daily, hourly, yearly). Empty when the company hides it. |
| `category`, `subcategory` | OCC's job category and subcategory. |
| `employmentType`, `workSchedule`, `workModel` | Contract (permanent, temporary...), schedule (full time, part time...) and onsite, hybrid or remote. |
| `education` | Minimum education asked for. |
| `benefits`, `skills`, `screeningQuestions` | Lists of benefits, required skills and the questions applicants must answer. |
| `description` | Full job description as plain text. |
| `companyLogo`, `companyJobsUrl` | Company logo and the page with all its jobs. |
| `postedAt`, `expiresAt` | Posting and expiry dates (YYYY-MM-DD). |
| `scrapedAt` | When the row was collected (UTC). |
| `error` | Only present when a job's details didn't load. |

### 💡 Use cases

#### 💰 Salary benchmark for sales roles in Jalisco

```json
{ "maxItems": 1000, "keywords": ["vendedor"], "locations": ["Jalisco"], "minSalary": 10000 }
```

#### 🏠 Remote IT jobs posted this week

```json
{ "maxItems": 500, "categories": ["tecnologias-de-la-informacion-sistemas"], "workModels": ["remote"], "postedWithin": "7" }
```

#### 🎓 Internships for students in Monterrey and CDMX

```json
{ "maxItems": 300, "locations": ["Monterrey", "Ciudad de México"], "contractTypes": ["becario-practicas"] }
```

#### 🗺️ The whole board, every job (leave Maximum jobs empty)

```json
{ "keywords": [] }
```

#### 🔗 Reuse a search you built on the site

```json
{ "maxItems": 200, "pageUrl": "https://www.occ.com.mx/empleos/de-contador/en-nuevo-leon/?smin=20000" }
```

### ⚙️ How the input is organised

| Section | What it's for |
| --- | --- |
| **Maximum jobs** | Always first, caps the whole run. Empty means no limit. |
| **Search** | Keywords, locations, or a pasted OCC search link. |
| **Job filters** | Category, work model, contract type, education, minimum and maximum salary, posting date, sort order. |

### 💰 Pricing

Pay-per-event: a one-time **$0.003** when the run starts, plus a price per job saved to your dataset. The price depends on your Apify plan tier:

| Your Apify plan | Price per job |
| --- | --- |
| Free | $0.014 |
| Bronze | $0.0125 |
| Silver | $0.011 |
| Gold / Platinum / Diamond | $0.01 |

Approximate total cost (includes the $0.003 start fee):

| Jobs collected | Free | Bronze | Silver | Gold+ |
| --- | --- | --- | --- | --- |
| 100 | $1.40 | $1.25 | $1.10 | $1.00 |
| 1,000 | $14.00 | $12.50 | $11.00 | $10.00 |
| 10,000 | $140.00 | $125.00 | $110.00 | $100.00 |

New Apify accounts start with $5 in free credit. On the Free plan a run saves up to 10 jobs.

### 🚀 Run it

1. Create a free Apify account with $5 in credit.
2. Open the OCC Mundial Jobs Scraper.
3. Type a keyword (or keep the prefilled one), add locations or filters if you like, set Maximum jobs, then click **Start**.
4. Export the results as CSV, Excel, JSON, or XML from the Dataset tab.

Run it programmatically through the Apify API (`run-sync-get-dataset-items`) or the ApifyClient for JavaScript and Python, and schedule it with Apify's built-in Scheduler.

### 🤖 Use with AI agents (MCP)

Give an AI agent live access to OCC jobs through the Model Context Protocol:

```
claude mcp add --transport http apify "https://mcp.apify.com?tools=normdata/occ-scraper"
```

Then prompt it in plain language to run the scraper and read back the results.

### 🔧 Troubleshooting

**A location was skipped.**
Use a state ("Jalisco", "Nuevo León") or a city ("Guadalajara", "Monterrey"). Accents are optional. If every location you gave is unrecognizable, the run stops with 0 results instead of searching all of Mexico.

**Salary fields are empty.**
The company chose to hide the salary ("Si el reclutador te contacta podrás conocer el sueldo"). The salary filters still work on those jobs because OCC applies them on its side.

**`company` is empty.**
The employer posted it as confidential (`confidentialCompany` is true).

**A row has an `error` field.**
That job's details didn't load; the row keeps its ID, link and search info.

**Fewer jobs than OCC's counter.**
A few jobs close between the search and the detail request; closed jobs are dropped instead of saved half empty.

### ❓ FAQ

| Question | Answer |
| --- | --- |
| Do I need an OCC account? | No. Only public job data is read. |
| Does it need a proxy? | No. |
| Is there a limit on results? | No. Searches bigger than OCC's 10,000-job paging limit are split, so you can collect the whole board. |
| Can I search several keywords and cities in one run? | Yes. Each combination runs its own search, results are shared fairly and duplicates removed. |
| Are salaries numbers? | Yes, `salaryMin` and `salaryMax` in MXN with `salaryPeriod`, plus the original text in `salary`. |
| Does it include recruiter contact details? | No. Recruiter names, phones and emails are personal data and are left out on purpose. |
| Is the data live? | Yes, read fresh on every run. |
| Can I schedule it? | Yes, with Apify's built-in Scheduler, for example daily with Posted within set to Today. |

### 🛡️ Limits & responsible use

This Actor reads only OCC's public job data. It never signs in and never applies to jobs. It does not collect recruiter personal data. Use the data in line with OCC's terms and applicable law (LFPDPPP).

### 📧 Contact

Need a scraper for a different site, or found something wrong with this one? norm.data.scrapers@gmail.com

### 🧪 Local development

```powershell
bun install
bun run typecheck
bun test/qa.mjs
apify run
```

Local results are stored in `storage/datasets/default`.

# Actor input Schema

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

Stop after this many jobs. Leave empty for no limit (the run stops once the matching jobs run out). The Apify Free plan is always capped at 10.

## `keywords` (type: `array`):

One or more searches, in Spanish as people search on OCC, e.g. "vendedor", "contador", "desarrollador java". Each one runs its own search and is tagged on every row it produces.

## `locations` (type: `array`):

Mexican states or cities, e.g. "Jalisco", "Monterrey", "Ciudad de México". Each location runs its own search. Leave empty for all of Mexico.

## `pageUrl` (type: `string`):

Already filtered a search on occ.com.mx? Paste that page's URL and it's reused exactly; every other search field and filter is then ignored.

## `categories` (type: `array`):

Only jobs in these OCC categories. Each one runs its own search.

## `workModels` (type: `array`):

On-site, hybrid or remote.

## `contractTypes` (type: `array`):

Only these types of contract.

## `education` (type: `array`):

Only jobs asking for this education level.

## `minSalary` (type: `integer`):

Only jobs paying at least this much per month, e.g. 15000. Jobs that hide their salary are left out when you set this.

## `maxSalary` (type: `integer`):

Only jobs paying up to this much per month.

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

Only jobs published in this window.

## `sortBy` (type: `string`):

Newest first (default) or OCC's own relevance order.

## Actor input object example

```json
{
  "maxItems": 10,
  "keywords": [
    "vendedor"
  ],
  "locations": [
    "Jalisco",
    "Monterrey"
  ],
  "pageUrl": "https://www.occ.com.mx/empleos/de-vendedor/en-jalisco/?tm=7",
  "postedWithin": "any",
  "sortBy": "newest"
}
```

# Actor output Schema

## `jobs` (type: `string`):

One row per job.

# 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 = {
    "maxItems": 10,
    "keywords": [
        "vendedor"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("normdata/occ-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 = {
    "maxItems": 10,
    "keywords": ["vendedor"],
}

# Run the Actor and wait for it to finish
run = client.actor("normdata/occ-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 '{
  "maxItems": 10,
  "keywords": [
    "vendedor"
  ]
}' |
apify call normdata/occ-scraper --silent --output-dataset

```

## MCP server setup

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