# Catho Jobs Scraper | Salary, Benefits & Company Intel (`corvuslab/catho-scraper`) Actor

Scrape job listings from Catho.com.br, Brazil's largest job board. Get structured salary breakdowns (min/max), benefits lists, contract types, work schedules, and company details — 30+ fields per listing with incremental monitoring and AI-ready output.

- **URL**: https://apify.com/corvuslab/catho-scraper.md
- **Developed by:** [Corvuslab](https://apify.com/corvuslab) (community)
- **Categories:** Jobs, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 results

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/platform/actors/running/actors-in-store#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

### What does Catho Jobs Scraper do?

Extract job listings from [Catho.com.br](https://www.catho.com.br/) — Brazil's largest job board — with structured salary data (min/max/display), benefits lists, contract types, work schedules, remote flags, company intelligence and full descriptions in three formats. Run a keyword search, filter by city or state, or paste URLs directly. No code needed — get results as JSON, CSV, Excel or via the API, optimized for AI agents with compact output mode.

Give it a search keyword (e.g. `analista`, `desenvolvedor`) and, optionally, a location (e.g. `Sao Paulo SP`), and it returns every matching job as a structured record. For each job you get the title, company, a full location hierarchy (city, state, postal code), parsed salary values (min/max), benefits list, contract type, work schedule, remote flag, vacancy count and the company's description, industry, size and employee count. Turn on **Fetch full details** to also pull the job description in three formats (text, HTML, Markdown) and contact details extracted from the listing.

> New to Apify? You can sign up for free and use the included monthly platform credit to try this Actor.

**Why this scraper**

- ⚡ **Fast & low-cost** — runs without a proxy at typical volumes, so large runs stay remarkably cheap.
- 🧾 **Rich, typed records** — 30+ structured fields per job listing, not raw HTML.
- ♻️ **Cheap to monitor** — incremental mode re-scrapes only what changed (see below).
- 🔔 **Notifications built in** — Telegram, Slack, Discord or any webhook.
- 🤖 **AI- & API-ready** — compact output, MCP-friendly, one-click integrations.

***

### Key features

- 🔍 **Search or URL scraping** — run a keyword + location search, or paste Catho search and detail-page URLs directly.
- 💰 **Structured salary data** — parsed `salaryMin` / `salaryMax` values plus the display string, ready for filtering and analysis without regex.
- 🎁 **Benefits & perks** — the full benefits list and count from every listing (Vale-transporte, Tiquete alimentacao and dozens more).
- 💼 **Contract & schedule** — contract type (CLT, PJ, freelance, etc.), work schedule text, remote flag and vacancy count.
- 🏢 **Company intelligence** — company description, industry, size tier and employee count for every employer.
- 📄 **Full descriptions in 3 formats** — plain text, HTML and Markdown, so you pick the one your pipeline needs.
- 🗺️ **Location hierarchy** — city, state, state code, country and postal code, not just a raw location string.
- 📇 **Contacts & lead gen** — emails, phones, URLs and social profiles extracted from job descriptions; filter with `requireContact` to keep only listings with contact details.
- ♻️ **Incremental monitoring** — schedule it and get only what changed (NEW / UPDATED / EXPIRED); unchanged items are skipped before their page is even fetched.
- 🔔 **Notifications** — Telegram, Slack, Discord or any webhook (n8n / Make / Zapier).
- 🤖 **AI-ready** — compact + drop-empty output modes keep payloads small for LLMs and MCP.

***

### How to scrape Catho

1. Open the actor and enter a **search keyword** (e.g. `analista`) and optionally a **location** (e.g. `Sao Paulo SP`) — or paste a Catho URL.
2. Set **Max results** and choose whether to **fetch full details** (salary breakdown, benefits, company info).
3. (Optional) Turn on **incremental mode** and a **notification** channel, then **Schedule** it.
4. Click **Start**.
5. Download the data as **JSON, CSV or Excel**, or pull it from the **API**.

New to Apify? Create a free account — it comes with monthly credit, no credit card required.

***

### Input

Configure it in the visual editor — no code needed — or pass JSON via the API.

| Field | What it does |
|---|---|
| `query` | Keyword search — comma-separate for multiple searches, each de-duplicated. |
| `location` | City or state filter, e.g. `Sao Paulo SP`, `Rio de Janeiro RJ`. |
| `startUrls` | Scrape specific Catho search or detail-page URLs directly. |
| `maxResults` | Cap the number of records (default 25, `0` = unlimited). |
| `includeDetails` | Fetch each job's full page for salary breakdown, benefits, company info and more. On by default. |
| `requireContact` | Keep only listings with an email, phone or both — built-in lead-gen filter. |
| `descriptionFormat` | Which description format(s) to include: `all`, `text`, `html` or `markdown`. |
| `compact` | Return only core fields — ideal for AI agents and MCP clients. |
| `excludeEmptyFields` | Remove null/empty fields from each record for cleaner output. |
| `incrementalMode` | Emit only what changed since the last run (NEW / UPDATED / EXPIRED). |

...and **23 inputs** in total — the table shows the essentials; the rest cover notification channels (Telegram, Slack, Discord, webhooks), incremental tuning (`stateKey`, `emitUnchanged`, `emitExpired`) and advanced settings (proxy, retries), all in the visual editor.

#### Example inputs

```json
{ "query": "analista", "location": "sao-paulo-sp", "maxResults": 100 }
```

```json
{ "query": "desenvolvedor, engenheiro", "includeDetails": true }
```

```json
{ "query": "gerente", "incrementalMode": true, "telegramChatId": "-100123456789" }
```

***

### Output

Each item in the dataset is one job. Every record includes the core fields; enabling **Fetch full details** (on by default) adds the description, benefits, salary breakdown, categories and company intelligence. Here's a full example record:

```json
{
  "id": "38019680",
  "title": "Analista de Atendimento",
  "url": "https://www.catho.com.br/vagas/analista-de-atendimento/38019680",
  "company": "Riba Brasil",
  "location": "Belem",
  "city": "Belem",
  "state": "Para",
  "stateCode": "PA",
  "country": "Brasil",
  "postalCode": "66050-380",
  "salary": "R$ 2.524",
  "salaryDisplay": "A partir de R$ 2.000,00",
  "salaryMin": 2524.0,
  "salaryMax": null,
  "contractType": "CLT (Efetivo)",
  "workSchedule": "Segunda ate sexta-feira: 9h as 18h, com intervalo de almoco. Sabado: 9h as 13h.",
  "workType": null,
  "isRemote": false,
  "vacancies": 1,
  "description": "Conduzir o processo de atendimento B2C para locacao de motos eletricas. Oferecer o atendimento presencial com gentileza e eficiencia. Capturar, tratar e converter leads em clientes ativos ...",
  "benefits": ["Tiquete alimentacao", "Vale-transporte"],
  "benefitsCount": 2,
  "categories": ["Administracao", "Telemarketing", "Administracao"],
  "subcategories": ["Administrativo/ Operacional", "Atendimento ao Cliente/ Call Center/ Telemarketing", "Administrativa"],
  "careers": ["Analista de Atendimento"],
  "postedAt": "2026-08-18T18:29:20",
  "updatedAt": "2026-08-18T18:29:20",
  "expiresAt": "2026-11-16T18:29:20",
  "isSponsored": true,
  "companyDescription": "Consultoria em recursos humanos.",
  "companyIndustry": "Recursos Humanos",
  "companySize": "Small",
  "companyEmployeeCount": 2,
  "source": "catho.com.br",
  "scrapedAt": "2026-08-19T10:52:48.041128+00:00"
}
```

Each record can also include `descriptionHtml` and `descriptionMarkdown` — choose the format with the **Description format** input. When incremental mode is on, records carry a `changeType` field (NEW / UPDATED / EXPIRED).

#### Data fields

- **Core** — `id`, `title`, `url`, `company`, `location`, `salary`, `contractType`, `source`, `scrapedAt`.
- **Salary breakdown** — `salary`, `salaryDisplay`, `salaryMin`, `salaryMax` — parsed numeric values ready for filtering.
- **Employment** — `contractType`, `workSchedule`, `workType`, `isRemote`, `vacancies`.
- **Location** — `city`, `state`, `stateCode`, `country`, `postalCode` — full geographic hierarchy.
- **Description** — `description`, `descriptionHtml`, `descriptionMarkdown` — three formats from one fetch.
- **Benefits & categories** — `benefits` (list), `benefitsCount`, `categories`, `subcategories`, `careers`.
- **Dates** — `postedAt`, `updatedAt`, `expiresAt`, `dateLabel`, `isSponsored`.
- **Company** — `companyDescription`, `companyIndustry`, `companySize`, `companyEmployeeCount`.
- **Contacts & signals** — `extractedEmails`, `extractedPhones`, `extractedUrls`, `socialProfiles`.
- **Tracking** — `searchKeyword`, `detailFetched`, `contentHash`, `changeType`, `isRepost`, `repostOfId`, `repostDetectedAt`.

Every field is present in standard mode (missing values are `null`); **compact mode** returns the core fields only, for lean AI/MCP payloads. With **`excludeEmptyFields`** enabled, null/empty fields are omitted entirely.

***

### What can you do with Catho data?

- **Lead generation** — filter for listings with contact details (`requireContact`) and feed them straight into your CRM or outreach pipeline.
- **Market & salary research** — analyze salary ranges, benefits and contract types across roles, cities and industries in the Brazilian job market.
- **Vacancy monitoring** — schedule it with incremental mode + notifications for a live feed of new, updated and expired positions.
- **Competitive hiring intel** — track which companies are hiring, what they offer, and how their packages compare over time.
- **Enrichment & aggregation** — feed clean, structured job data into your own app, spreadsheet or data warehouse.
- **AI agents & pipelines** — compact output plugs straight into LLM/MCP workflows for automated analysis.

***

### Incremental monitoring — pay for changes, not repeats

Schedule the actor and turn on **incremental mode**: each run compares against the last and emits only **NEW / UPDATED / EXPIRED** records — unchanged items are skipped *before* their detail page is fetched, so a daily watch costs a fraction of a full re-scrape.

| Daily churn | of 1,000 tracked | billable records | you save |
|---|---|---|---|
| 5 % | 1,000 | 50 | **95 %** |
| 15 % | 1,000 | 150 | **85 %** |
| 30 % | 1,000 | 300 | **70 %** |

The first run seeds the baseline and bills in full; every run after that bills only the delta.

***

### Pricing

This Actor uses the **pay-per-event** pricing model: a small fee at run start plus a per-record fee. It runs on plain HTTP (no headless browser), so the underlying platform cost is a fraction of a cent per run.

See the Actor's **Pricing** tab for exact current prices.

***

### Integrations & export

Export to **JSON, CSV, Excel** or an HTML table, or pull from the **REST API** and the **JavaScript / Python** clients. Runs on a **schedule**, connects to **Google Sheets, Slack, Make, Zapier and n8n**, and works as an **MCP tool** for AI agents — compact mode keeps token usage small.

***

### Using the API

You can run this Actor from your own code. Example with the Apify Python client:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")

run_input = {
    "query": "analista",
    "location": "sao-paulo-sp",
    "maxResults": 50,
}

run = client.actor("corvuslab/catho-scraper").call(run_input=run_input)

print("Results: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

The Actor also works with the JavaScript/TypeScript client, the Apify CLI and the REST API.

***

### FAQ

**Do I need a proxy or login?** No — the scraper runs out of the box without a proxy or any credentials; Apify Proxy is available under Advanced for high-volume runs.

**Can I get only new jobs on a schedule?** Yes — turn on incremental mode and schedule it; each run emits only what changed and can notify your channel automatically.

**What formats can I export?** JSON, CSV, Excel, HTML table, or via the API.

**Can I filter by location?** Yes — enter a city and state (e.g. `Sao Paulo SP`, `Rio de Janeiro RJ`, `Campinas SP`) and results are scoped to that area.

**How do I get salary data?** Enable **Fetch full details** (on by default). Each record includes `salary`, `salaryDisplay`, `salaryMin` and `salaryMax`.

**Is it good for AI agents?** Yes — enable compact mode; the output is small, structured and MCP-friendly.

**How many records can I get?** As many as Catho has for your search — set `maxResults` to 0 for unlimited.

**Can it notify me when new jobs appear?** Yes — add a Telegram, Slack, Discord or generic webhook target under Notifications, and combine with incremental mode so you only get pinged about new and updated jobs.

**Is scraping Catho legal?** This actor collects only **publicly available** data on Catho.com.br. You are responsible for how you use the extracted data — in particular any personal information — and for complying with the site's terms and applicable law (including Brazil's LGPD and the GDPR where they apply). Not affiliated with, endorsed by, or sponsored by Catho or Seek Limited.

***

**Keywords:** Catho scraper · Catho API · catho.com.br scraper · Brazil job scraper · Brazil job board · vagas Catho · empregos Brasil · Catho data extraction · Catho job listings · scrape Catho · job scraper Brazil · salary data Brazil · Brazilian job market · export jobs CSV · export jobs JSON · job monitoring Brazil · lead generation Brazil · MCP tool AI agents · no-code scraper

# Actor input Schema

## `query` (type: `string`):

Job title, skill or keyword to search for. Separate multiple searches with commas — each runs as its own search and results are merged and de-duplicated.

## `location` (type: `string`):

City or state to filter by, e.g. 'São Paulo SP', 'Rio de Janeiro RJ', 'Campinas SP'. Converted to a URL slug automatically.

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

Paste Catho search or detail-page URLs to scrape directly. Overrides keyword/location when provided.

## `maxResults` (type: `integer`):

Maximum number of records to return. Set 0 for unlimited.

## `ignoreUrlFailures` (type: `boolean`):

Skip URLs that cannot be interpreted instead of failing the whole run.

## `requireContact` (type: `string`):

Keep only records that include a contact. off = keep everything; email / phone = require that channel; either = at least one; both = email and phone.

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

Fetch each job's detail page for the richer fields (description, benefits, salary breakdown, company info). Turn off for the fastest, cheapest runs.

## `descriptionFormat` (type: `string`):

Which representation(s) of the job description to include.

## `compact` (type: `boolean`):

Emit only the core fields (id, title, url, company, location, salary, contract, source). Ideal for AI agents and MCP clients.

## `excludeEmptyFields` (type: `boolean`):

Remove null, empty-string and empty-array fields from each record.

## `incrementalMode` (type: `boolean`):

Track state between runs and tag every record with a changeType (NEW / UPDATED / UNCHANGED / EXPIRED).

## `stateKey` (type: `string`):

Stable name for the tracked search. Leave empty to derive one automatically from your search settings.

## `emitUnchanged` (type: `boolean`):

Also emit records that have not changed since the previous run.

## `emitExpired` (type: `boolean`):

Emit records for jobs present last run but gone now.

## `telegramToken` (type: `string`):

Bot token from @BotFather.

## `telegramChatId` (type: `string`):

Chat or channel ID, e.g. "-100123456789" or "@yourchannel".

## `slackWebhookUrl` (type: `string`):

Slack incoming-webhook URL.

## `discordWebhookUrl` (type: `string`):

Discord incoming-webhook URL.

## `webhookUrl` (type: `string`):

Any HTTPS endpoint. Receives a JSON POST with the matched records — works with n8n, Make and Zapier.

## `webhookHeaders` (type: `object`):

Extra headers for the webhook request, e.g. {"Authorization": "Bearer xyz"}.

## `notificationLimit` (type: `integer`):

How many records to include in each notification message.

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

Optional. Catho works without a proxy — enable only if you hit rate limits at high volume.

## `maxRequestRetries` (type: `integer`):

How many times to retry a failed request before giving up on it.

## Actor input object example

```json
{
  "query": "desenvolvedor, engenheiro",
  "location": "sao-paulo-sp",
  "maxResults": 25,
  "ignoreUrlFailures": true,
  "requireContact": "off",
  "includeDetails": true,
  "descriptionFormat": "all",
  "compact": false,
  "excludeEmptyFields": false,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "notificationLimit": 5,
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "maxRequestRetries": 3
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

## `allItems` (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 = {
    "query": "analista"
};

// Run the Actor and wait for it to finish
const run = await client.actor("corvuslab/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 = { "query": "analista" }

# Run the Actor and wait for it to finish
run = client.actor("corvuslab/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 '{
  "query": "analista"
}' |
apify call corvuslab/catho-scraper --silent --output-dataset

```

## MCP server setup

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