# Gupy Jobs Scraper (`khadinakbar/gupy-jobs-scraper`) Actor

Scrape public Gupy Brazil job listings from company career pages (\*.gupy.io) and the employability portal JSON API. Returns title, company, location, employment type, workplace type, department, description, and job URL for recruiting and labor-market research.

- **URL**: https://apify.com/khadinakbar/gupy-jobs-scraper.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** Jobs, Lead generation, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 validated gupy job scrapeds

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?

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

## Gupy Jobs Scraper — Brazil Career Pages & Portal Search

Use this Apify Actor to extract **public Gupy Brazil job listings** from company career pages (`*.gupy.io`) and keyword search on the employability portal API. Recruiters, job-board operators, and hiring-intel agents get a structured dataset of flat rows with title, company, location, workplace type, department, description, and apply URL — cookieless, no login, MCP-ready.

Use this Actor when you need live public Gupy openings for Brazilian employers into JSON. When the next step is Indeed or multi-ATS boards, continue with a sibling jobs Actor instead.

### Best fit for this Actor

- You need **public Gupy Brazil jobs** from a career page URL/subdomain (for example `https://ambev.gupy.io/`) or portal keywords such as `desenvolvedor`.
- You want flat fields (`title`, `companyName`, `location`, `workplaceType`, `jobUrl`, `descriptionText`) plus optional portal description enrich.
- You want one MCP-ready tool with terminal `OUTPUT.outcome` and Pay per event billing.
- For Indeed, LinkedIn, or multi-ATS (Greenhouse/Lever/Ashby) boards, route to a sibling jobs Actor.

### Use case: Ambev career monitoring sheet

A Brazil recruiting analyst schedules this Actor daily with `careerPageUrls: ["https://ambev.gupy.io/"]` and `maxResults: 50`. Each row has `title`, `department`, `location`, `workplaceType`, and `jobUrl`. They dedupe on `jobId`, flag new openings, then turn on a portal keyword follow-up for remote `desenvolvedor` roles when the team needs market-wide tech sourcing.

### Quick start input

```json
{
  "careerPageUrls": ["https://ambev.gupy.io/"],
  "searchKeywords": [],
  "maxResults": 25,
  "city": "",
  "state": "",
  "titleIncludes": "",
  "departmentIncludes": "",
  "workplaceType": "any",
  "remoteOnly": false,
  "includeTalentPool": false,
  "includeDescriptions": true
}
```

Portal discovery example:

```json
{
  "searchKeywords": ["desenvolvedor"],
  "maxResults": 20,
  "remoteOnly": true,
  "includeDescriptions": true
}
```

Supply at least one of `careerPageUrls` or `searchKeywords`. Prefill keeps quality tests at five Ambev jobs.

### What data you receive

One dataset row per unique public Gupy job.

```json
{
  "jobId": "11445944",
  "title": "Afirmativa PCD - Vendedor(a) Externo - Representante de Vendas (Maceió/AL)",
  "companyName": "Ambev",
  "companyId": "119",
  "careerPageSubdomain": "ambev",
  "location": "Maceió, Alagoas, Brasil",
  "city": "Maceió",
  "state": "Alagoas",
  "country": "Brasil",
  "department": "Sales",
  "employmentType": "effective",
  "workplaceType": "on-site",
  "isRemote": false,
  "jobUrl": "https://ambev.gupy.io/job/eyJqb2JJZCI6MTE0NDU5NDQsInNvdXJjZSI6Imd1cHlfcG9ydGFsIn0=?jobBoardSource=gupy_portal",
  "careerPageUrl": "https://ambev.gupy.io/",
  "sourceApiUrl": "https://employability-portal.gupy.io/api/v1/jobs?companyId=119&limit=100&offset=0",
  "sourceMode": "company_career",
  "scrapedAt": "2026-09-21T12:11:11.614Z"
}
```

| Field | Description |
|-------|-------------|
| title, companyName, department | Public role and employer data |
| location, city, state, country, isRemote, workplaceType | Public location and work arrangement |
| employmentType, publishedAt, applicationDeadline | Job type and dates when Gupy exposes them |
| descriptionText, descriptionHtml | Public description when portal enrich is available |
| jobUrl, careerPageUrl, jobId | Canonical public URLs and stable id |
| sourceApiUrl, sourceMode, scrapedAt | Provenance and retrieval timestamp |

You can download the dataset as JSON, HTML, CSV, or Excel from the Apify Console Output tab.

### Pricing

#### Startup billing and empty runs

The `apify-actor-start` event costs **$0.00005 per startup unit**. Apify charges one startup unit per GB of allocated memory, with a minimum of one unit, so a 2 GB run incurs two units. This startup charge still applies when input is invalid, no results are found, or an upstream request fails. Statements about free, unbilled, or skipped results refer only to the corresponding result event; they do not waive the startup charge. Apify platform usage is included in the event prices and is not passed through as an additional customer charge. Check the live [Pricing tab](https://apify.com/khadinakbar/gupy-jobs-scraper/pricing) for current events, tiers, and rates. Result limits cap result events, not the entire run cost.

Pay per event with Apify platform usage included (`isPPEPlatformUsagePaidByUser: false`). Open the live Pricing tab in Apify Console for the current source of truth.

| Event | When | Price |
|---|---|---:|
| `apify-actor-start` | Every Actor start | $0.00005 |
| `job-scraped` | Each accepted validated job row | $0.003 |

A 25-job sample is about `$0.07505` in events plus platform compute. Invalid input and valid-empty searches leave `job-scraped` events unbilled.

### How it works

1. Career pages: read public HTML `__NEXT_DATA__` listing cards (including department).
2. Portal enrich / search: page `employability-portal.gupy.io/api/v1/jobs` until an empty page or `maxResults`.
3. Each accepted row is charged then pushed (`Actor.charge` → `pushData`).
4. Terminal `OUTPUT` / `RUN_SUMMARY` use COMPLETE, PARTIAL, VALID_EMPTY, INVALID_INPUT, UPSTREAM_FAILED, or CONFIG_ERROR.

### Honest contract and best results

- Public candidate-facing career pages and portal JSON only. No Gupy admin login or `api.gupy.io` company token.
- Keep `maxResults` small while testing; raise it after a career page or keyword returns useful rows.
- Prefer a known `*.gupy.io` URL for employer monitoring; use `searchKeywords` for Brazil-wide discovery.
- Leave `includeTalentPool` false for active openings; set it true only when banco-de-talentos rows matter.
- Leave `includeDescriptions` true so career-page cards get portal description enrich when `companyId` is known.
- Combine `city`, `state`, `remoteOnly`, or `workplaceType` before writing rows so filters apply before billing.

### Why agents choose this Actor

- One tool for company career pages and portal keyword search.
- Predictable PPE with platform usage included and a hard `maxResults` ceiling (up to 1,000 jobs per Actor start).
- Flat fields stay inside a small token budget for MCP clients.
- Terminal `OUTPUT.outcome` makes empty, upstream-outage, and invalid-input states machine-readable.

### Agent checklist

1. Supply `careerPageUrls` and/or `searchKeywords`.
2. Cap `maxResults` to the budget you can spend at `$0.003` per job.
3. After completion, read `OUTPUT.outcome`, then the dataset.
4. Zero rows with `VALID_EMPTY` means sources responded but filters matched nothing public — change keyword, city, or employer URL.
5. When `OUTPUT.outcome` is `UPSTREAM_FAILED`, retry once with a fresh session before escalating.

### Use through the API

```bash
curl "https://api.apify.com/v2/acts/khadinakbar~gupy-jobs-scraper/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "careerPageUrls": ["https://ambev.gupy.io/"],
    "maxResults": 25,
    "includeTalentPool": false,
    "includeDescriptions": true
  }'
```

When the Actor completes, read dataset items from the default dataset and the `OUTPUT` record from the default key-value store.

### Use with AI agents through Apify MCP

> Fetch public Gupy Brazil jobs for Ambev from https://ambev.gupy.io/. Return up to 25 rows with title, company, location, workplace type, and jobUrl. Keep talent-pool rows excluded. Stay on public career-page and portal fields only.

Point the MCP client at <https://mcp.apify.com>?tools=khadinakbar/gupy-jobs-scraper, call `khadinakbar/gupy-jobs-scraper`, then read the dataset and `OUTPUT.outcome`.

### Builder's note

I built this Actor on Gupy's public career `__NEXT_DATA__` payload and the employability portal JSON after finding that career listings alone omit long descriptions. In my testing, portal enrich by `companyId` fills `descriptionText` when Gupy exposes it, and portal `pagination.total` can under-count so the Actor pages until an empty page. My goal is truthful billing: only validated public jobs with a job ID, title, company, and public URL receive the `job-scraped` event.

### Connect the workflow

When the next board is Indeed, continue with [Indeed Job Scraper](https://apify.com/khadinakbar/indeed-job-scraper) for listing-level Indeed research after Gupy discovery.

For Ashby-hosted career sites after a Gupy employer scan, use [Ashby Jobs Scraper](https://apify.com/khadinakbar/ashby-jobs-scraper).

When you need a multi-ATS hub (Greenhouse, Lever, Ashby, and more) instead of Gupy-only, start with [ATS Jobs Scraper](https://apify.com/khadinakbar/ats-jobs-scraper).

### FAQ and responsible use

**Is this affiliated with Gupy?** Gupy is a trademark of its owner. This independent Actor is not affiliated with, associated with, or endorsed by Gupy.

**What inputs are supported?** Public `*.gupy.io` career URLs/subdomains and portal search keywords. LinkedIn, Indeed, or Gupy admin URLs belong in other Actors.

**Why was my result empty?** A valid keyword or career page with zero public matches finishes `SUCCEEDED` / `VALID_EMPTY`. Missing career pages and keywords finishes `INVALID_INPUT`. When every source is unavailable the outcome is `UPSTREAM_FAILED`.

**Why is description empty?** Career-page HTML cards are short. Keep `includeDescriptions` enabled so the Actor enriches via the portal API when the company ID is known.

**Does it apply for jobs or collect candidates?** No. It only reads public postings and returns the public `jobUrl`.

Open the Actor **Issues** tab for bugs. This Actor is independent research tooling, not legal, recruiting, or employment advice. Use the data in accordance with Gupy's policies, applicable law, and your own compliance rules.

# Changelog

This Actor's version history is a separate document: https://apify.com/khadinakbar/gupy-jobs-scraper/changelog.md

# Actor input Schema

## `careerPageUrls` (type: `array`):

Enter public Gupy career hosts such as ambev or https://ambev.gupy.io/. The actor reads the public career page and optionally enriches descriptions from Gupy's employability portal API. Provide this and/or searchKeywords. Do not paste LinkedIn, Indeed, or Gupy admin URLs.

## `searchKeywords` (type: `array`):

Search public Gupy portal listings by job title keyword, such as desenvolvedor or analista. Results come from employability-portal.gupy.io. Provide this and/or careerPageUrls. Leave empty when scraping only company career pages.

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

Caps validated job records written for the whole run across every career page and keyword. Enter an integer such as 50. Defaults to 100 and accepts 1 through 1,000. This is an output cap, not a page count.

## `city` (type: `string`):

Optionally keep jobs whose city contains this text, such as São Paulo. Matching is case-insensitive against Gupy's public city field. Leave blank to keep all cities.

## `state` (type: `string`):

Optionally keep jobs whose Brazilian state contains this text, such as São Paulo or Minas Gerais. Matching is case-insensitive against Gupy's public state field. Leave blank to keep all states.

## `locationIncludes` (type: `string`):

Optionally keep jobs whose combined city/state/country text contains this value. Matching is case-insensitive. Leave blank to keep every location. This does not geocode addresses.

## `titleIncludes` (type: `string`):

Optionally keep only jobs whose title contains this text, such as sênior. Matching is case-insensitive and uses literal text. Leave blank to keep all titles.

## `departmentIncludes` (type: `string`):

Optionally keep jobs whose department contains this text, such as Sales or Engineering. Department is available on company career pages; portal-only rows may leave it empty. Matching is case-insensitive.

## `workplaceType` (type: `string`):

Keep jobs matching this workplace arrangement. Choose any, remote, hybrid, or on-site. Defaults to any. Combined with remoteOnly when that checkbox is enabled.

## `remoteOnly` (type: `boolean`):

Keeps only jobs Gupy marks as remote workplace. Set true for remote-role research or false to retain all workplace types. Defaults to false.

## `includeTalentPool` (type: `boolean`):

Gupy career pages often list banco de talentos (talent pool) entries alongside active openings. Set true to keep them or false (default) to skip vacancy_type_talent_pool rows.

## `includeDescriptions` (type: `boolean`):

When true (default), include public description HTML/text from the portal API. Company career listings alone omit long descriptions, so the actor enriches via companyId when possible. Set false for smaller listing-only rows.

## Actor input object example

```json
{
  "careerPageUrls": [
    "ambev",
    "https://renner.gupy.io/"
  ],
  "searchKeywords": [
    "desenvolvedor",
    "python"
  ],
  "maxResults": 50,
  "city": "São Paulo",
  "state": "São Paulo",
  "locationIncludes": "remoto",
  "titleIncludes": "analista",
  "departmentIncludes": "Sales",
  "workplaceType": "remote",
  "remoteOnly": true,
  "includeTalentPool": false,
  "includeDescriptions": true
}
```

# Actor output Schema

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

Validated public Gupy job records returned by this run.

## `output` (type: `string`):

Compact outcome, item counts, warnings, and charged event totals.

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

Detailed source coverage, diagnostics, and billing information for this run.

# 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 = {
    "careerPageUrls": [
        "https://ambev.gupy.io/"
    ],
    "searchKeywords": [],
    "maxResults": 25,
    "city": "",
    "state": "",
    "locationIncludes": "",
    "titleIncludes": "",
    "departmentIncludes": "",
    "workplaceType": "any",
    "remoteOnly": false,
    "includeTalentPool": false,
    "includeDescriptions": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/gupy-jobs-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 = {
    "careerPageUrls": ["https://ambev.gupy.io/"],
    "searchKeywords": [],
    "maxResults": 25,
    "city": "",
    "state": "",
    "locationIncludes": "",
    "titleIncludes": "",
    "departmentIncludes": "",
    "workplaceType": "any",
    "remoteOnly": False,
    "includeTalentPool": False,
    "includeDescriptions": True,
}

# Run the Actor and wait for it to finish
run = client.actor("khadinakbar/gupy-jobs-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 '{
  "careerPageUrls": [
    "https://ambev.gupy.io/"
  ],
  "searchKeywords": [],
  "maxResults": 25,
  "city": "",
  "state": "",
  "locationIncludes": "",
  "titleIncludes": "",
  "departmentIncludes": "",
  "workplaceType": "any",
  "remoteOnly": false,
  "includeTalentPool": false,
  "includeDescriptions": true
}' |
apify call khadinakbar/gupy-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,khadinakbar/gupy-jobs-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/QQ0G8oIgrluO6vOko/builds/6AaqV0mKjTxhnmxSY/openapi.json
