# Catho Jobs Scraper (`normdata/catho-scraper`) Actor

Every job on Catho, Brazil's biggest job board, in one run: recruiters see who is hiring and at what salary, HR teams benchmark pay by role and city, and analysts track demand by area, contract type and work model. Full descriptions and benefits, 1,000 jobs in under a minute.

- **URL**: https://apify.com/normdata/catho-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)

## 💼 Catho Jobs Scraper

Extract job listings from **Catho**, Brazil's biggest job board: title, company, salary (as shown and as numbers), city, state, CEP, contract type, working hours, full description and the benefits list. Search by keyword, state or city, and filter by work model, contract, salary band, area and posting date. About **1,000 jobs with full details in under a minute**.

Catho lists more than 200,000 open jobs. This Actor reads the same public pages a job seeker sees, page by page with no result cap, and turns each job into a clean row ready for a spreadsheet, a CRM or a salary analysis.

### 🎯 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, city and contract type with real published salaries, already parsed into numbers.

#### 📈 Labor market analysts and journalists

Track demand by area, work model (remote, hybrid, on-site) and contract type across Brazil, on a schedule.

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

Feed an aggregator, alert service or matching model with fresh, structured Brazilian jobs.

### ✨ What it does

- **Search** by one or more keywords, in one or more states or cities, or across all of Brazil.
- **Filters Catho itself offers:** work model, contract type, professional area (78), salary band, salary shown only, posting date, and sort order.
- **No result cap:** walks every page of a search, not just the first few hundred jobs.
- **Full details by default:** full description, contract type, working hours, benefits list, every location with street and CEP, and the exact posting date.
- **Salary as numbers:** "R$ 5.500", "A partir de R$ 3.000,00" or "A combinar" become `salaryMin`, `salaryMax` and a `salaryToBeAgreed` flag.
- **Paste a search link:** reuse a search you already filtered on catho.com.br.

### 🏆 Why this scraper

- **Fast without shortcuts.** About 1,000 jobs with full details in under a minute, with no browser and no proxy.
- **Every filter, not just a keyword box.** Work model, contract, area, salary band and date are real inputs, not something you have to build into a URL by hand.
- **Numbers you can sort by.** Salaries are parsed from Brazilian formatting into numbers, and "A combinar" is flagged instead of mixed in.
- **Honest about what Catho shows.** Confidential companies stay confidential (`company` is empty and `confidentialCompany` is true). The work model is only filled in when you filter by it, because that's the only time Catho tells you.

### ⚖️ How it compares

| Capability | This actor | [scrapers_lat/catho-brasil-jobs-scraper](https://apify.com/scrapers_lat/catho-brasil-jobs-scraper) | [shahidirfan/Catho-Jobs-Scraper](https://apify.com/shahidirfan/Catho-Jobs-Scraper) |
|---|:--:|:--:|:--:|
| Several keywords and locations in one run | **yes** | keywords only | one of each |
| Work model, contract, area and salary filters | **yes** | no | no |
| Posting date filter and newest-first sort | **yes** | no | date only |
| Full job description | **yes** | excerpt | yes |
| Benefits list | **yes** | count only | no |
| Salary parsed into min/max numbers | **yes** | no | no |
| Every location with street and CEP | **yes** | no | no |
| Working hours | **yes** | no | no |
| Proxy | **none needed** | residential proxies | Apify Proxy recommended |
| Published speed | **~1,000 jobs/min with details** | not stated | ~500 jobs in ~2 min |

scrapers_lat also sells optional AI add-ons (summary, skills, salary estimate, translation) and a remote/home-office flag on every row. Catho has no structured work-model field on job pages, so this actor tags `workModel` from Catho's own filter instead of guessing from the description.

### 📦 What data you get

| Field | Description |
| --- | --- |
| `jobId`, `url` | Catho's job ID and the job page. |
| `title`, `company`, `confidentialCompany` | Job title and hiring company; confidential listings have no company name. |
| `vacancies` | How many openings the job offers. |
| `city`, `additionalCities` | Main city, and how many more cities the job is open in. |
| `salary`, `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryToBeAgreed` | The salary exactly as shown, the same as numbers in BRL, and whether it's "A combinar". |
| `benefitsCount` | Number of benefits shown on the listing. |
| `sponsored`, `recruiterActive` | Paid placement, and Catho's "active recruiter" badge. |
| `postedAt` | Posting date (YYYY-MM-DD). |
| `workModel` | Remote, hybrid or presential. Only present when you filter by work model. |
| `searchKeyword`, `searchLocation`, `source` | Which search produced the row, and always `Catho`. |
| `description`, `contractType`, `workHours`, `benefits`, `locations`, `state`, `postalCode`, `companyLogo` | From each job's own page. Present only when Full job details is on (the default). |
| `scrapedAt` | When the row was collected (UTC). |

### 💡 Use cases

#### 💰 Salary benchmark for developers in São Paulo

```json
{ "maxItems": 1000, "keywords": ["desenvolvedor"], "locations": ["SP"], "onlyWithSalary": true }
```

#### 🏠 Remote jobs only, newest first

```json
{ "maxItems": 300, "keywords": ["analista de dados", "desenvolvedor"], "workModels": ["remote"], "sortBy": "newest" }
```

#### 📋 PJ contractor roles posted this week

```json
{ "maxItems": 500, "contractTypes": ["6"], "postedWithin": "7" }
```

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

```json
{ "maxItems": 200, "pageUrl": "https://www.catho.com.br/vagas/enfermeiro/rj/?faixa_sal_id=5" }
```

### ⚙️ How the input is organised

| Section | What it's for |
| --- | --- |
| **Maximum jobs** | Always first, caps the whole run. |
| **Search** | Keywords, locations, or a pasted Catho search link. |
| **Job filters** | Work model, contract type, professional area, salary band, salary shown only, posting date, sort order. |
| **Details** | Full job details on or off. |

### 💰 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.

### 🚀 Run it

1. Create a free Apify account with $5 in credit.
2. Open the Catho 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 Catho jobs through the Model Context Protocol:

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

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

### 🔧 Troubleshooting

**A location was skipped.**
Use a state code ("SP") or "City - UF" ("Campinas - SP"). If every location you gave is unrecognizable, the run stops with 0 results instead of searching all of Brazil.

**Some jobs show another city than the one I searched.**
Those jobs are open in several cities (`additionalCities`); Catho lists them under each one. Every location is in `locations`.

**There's no `workModel` column.**
Catho only says whether a job is remote, hybrid or on-site when you filter by it. Pick one or more work models and every row gets tagged.

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

**A row has an `error` field.**
That job's own page didn't load (it may have just closed); the row keeps everything from the search results.

### ❓ FAQ

| Question | Answer |
| --- | --- |
| Do I need a Catho account? | No. Only public job pages are read. |
| Does it need a proxy? | No. |
| Is there a limit on results? | No. Every page of a search is read, so big searches return every job. |
| Can I search several keywords and cities in one run? | Yes. Each combination runs its own search, and rows from all of them are mixed fairly. |
| Are salaries numbers? | Yes, `salaryMin` and `salaryMax` in BRL, plus the original text in `salary`. |
| Does it include recruiter contact details? | No. Catho doesn't publish them on job pages. |
| 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 Catho's public job pages. It never signs in and never applies to jobs. Company names are business information; use the data in line with Catho's terms and applicable law (LGPD).

### 📧 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
node 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 Portuguese as people search on Catho, e.g. "desenvolvedor", "analista financeiro", "enfermeiro". Each one runs its own search and is tagged on every row it produces.

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

States or cities, e.g. "SP", "RJ" or "Campinas - SP". Each location runs its own search. Leave empty for all of Brazil.

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

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

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

Remote, hybrid or on-site. Picking one or more also adds a workModel column to every row, since Catho only shows the model when you filter by it.

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

Only these types of contract.

## `areas` (type: `array`):

Only jobs in these areas.

## `salaryBand` (type: `string`):

Monthly salary band, as Catho groups it.

## `onlyWithSalary` (type: `boolean`):

Hide jobs whose salary is "A combinar" (to be agreed).

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

Only jobs published recently.

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

Most relevant first, or newest first.

## `fetchDetails` (type: `boolean`):

Opens each job to add the full description, contract type, working hours, benefits list, every location with street and CEP, and the exact posting date. Still fast (about 1,000 jobs in under a minute); turn off for a list-only run.

## Actor input object example

```json
{
  "maxItems": 10,
  "keywords": [
    "desenvolvedor"
  ],
  "locations": [
    "SP",
    "Belo Horizonte - MG"
  ],
  "pageUrl": "https://www.catho.com.br/vagas/desenvolvedor/sp/?faixa_sal_id=7",
  "salaryBand": "any",
  "postedWithin": "any",
  "sortBy": "relevance",
  "fetchDetails": true
}
```

# 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": [
        "desenvolvedor"
    ],
    "salaryBand": "any",
    "onlyWithSalary": false,
    "postedWithin": "any",
    "sortBy": "relevance",
    "fetchDetails": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("normdata/catho-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": ["desenvolvedor"],
    "salaryBand": "any",
    "onlyWithSalary": False,
    "postedWithin": "any",
    "sortBy": "relevance",
    "fetchDetails": True,
}

# Run the Actor and wait for it to finish
run = client.actor("normdata/catho-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": [
    "desenvolvedor"
  ],
  "salaryBand": "any",
  "onlyWithSalary": false,
  "postedWithin": "any",
  "sortBy": "relevance",
  "fetchDetails": true
}' |
apify call normdata/catho-scraper --silent --output-dataset

```

## MCP server setup

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