# Emprego SAPO Scraper — Portugal Job Listings Data (`studio-amba/emprego-sapo-pt-scraper`) Actor

Scrape job listings from emprego.sapo.pt, the SAPO portal's jobs board in Portugal. Search by keyword, district, and category. Extract job titles, companies, locations, full descriptions, employment type, and posting dates. No login or cookies required.

- **URL**: https://apify.com/studio-amba/emprego-sapo-pt-scraper.md
- **Developed by:** [Studio Amba](https://apify.com/studio-amba) (community)
- **Categories:** Jobs
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 result scrapeds

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?

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 Emprego SAPO Scraper do?

**Emprego SAPO Scraper** extracts job listings from [emprego.sapo.pt](https://emprego.sapo.pt), the jobs board run by SAPO — Portugal Telecom's web portal. The scraper collects job titles, companies, locations, districts, employment type, remote-work status, industry, full descriptions, and posting dates for every listing matching your search.

Run it on the Apify platform to get structured Portuguese job market data via API, schedule recurring scrapes, and feed the results straight into your own tools. No login, cookies, or manual browsing required.

### Why use Emprego SAPO Scraper?

- **Coverage of a major Portuguese jobs board**: SAPO Emprego is one of the general-purpose national boards in Portugal, alongside Net-Empregos and the public employment service — this actor closes that gap in a Portugal jobs data pipeline.
- **Recruitment intelligence**: Track which companies are actively hiring, in which districts, and for which roles.
- **Salary and role research**: Pull structured descriptions at scale instead of reading listings one by one.
- **Lead generation**: Find companies posting jobs in a specific sector or region to target for sales or partnerships.
- **No technical setup**: Run directly from the Apify Console, or call the API from any programming language.

### How to scrape emprego.sapo.pt data

1. Go to the Emprego SAPO Scraper page on Apify.
2. Click **Try for free** to open the actor in the Apify Console.
3. Enter a search query in Portuguese (e.g., `programador`, `contabilista`, `enfermeiro`).
4. Optionally set a district (e.g., `Lisboa`, `Porto`) and a category filter.
5. Set the maximum number of results you want.
6. Click **Start** and wait for the run to finish.
7. Download your data as JSON, CSV, Excel, or connect it via API.

### Input

| Field | Type | Description |
|-------|------|-------------|
| `searchQuery` | String | Job search keyword in Portuguese. Defaults to `emprego` if left empty. |
| `location` | String | Portuguese district (e.g., `Lisboa`, `Porto`, `Braga`). Leave empty for all of Portugal. |
| `category` | String | Job category filter — pick from the dropdown (34 categories, e.g. IT, Engineering, Healthcare). |
| `maxResults` | Integer | Maximum listings to scrape (default: 100, max: 10,000). |
| `fetchFullDescription` | Boolean | When `true` (default), visits each job's detail page for the full description, employment type, industry, and remote flag. When `false`, only the short listing snippet is returned (faster, fewer requests). |
| `proxyConfiguration` | Object | Proxy settings. The site has no anti-bot protection, so the automatic default works fine. |

#### Example input

```json
{
    "searchQuery": "programador",
    "location": "Lisboa",
    "maxResults": 50,
    "fetchFullDescription": true,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
}
```

### Output

The scraper produces a dataset of job listings. Each item contains the following fields:

| Field | Type | Description |
|-------|------|-------------|
| `jobId` | String | Internal site identifier for the listing |
| `jobTitle` | String | Job position title |
| `company` | String | Hiring company name (`"N/A"` for anonymous employers) |
| `companyUrl` | String | Hiring company's own website, when published |
| `location` | String | City or municipality |
| `district` | String | Portuguese district |
| `employmentType` | String | e.g. `FULL_TIME` |
| `remote` | Boolean | `true` if the listing is marked as remote work |
| `industry` | String | Industry sector (only populated when `fetchFullDescription` is enabled) |
| `jobDescription` | String | Full job description text (or a short snippet when `fetchFullDescription` is `false`) |
| `postedDate` | String | Date posted (YYYY-MM-DD) |
| `validThrough` | String | Application deadline, when published |
| `anonymous` | Boolean | `true` when the employer's identity is hidden on the listing |
| `url` | String | Direct link to the listing on emprego.sapo.pt |
| `scrapedAt` | String | ISO 8601 timestamp of data collection |

#### Example output

```json
{
    "jobId": "c3d28e2c-c37f-4dc1-b3d1-7e87a08b1035",
    "jobTitle": "Programador(a)",
    "company": "NLS - New Link Solutions",
    "companyUrl": "https://nls-group.eu/index.php/pt/",
    "location": "Lisboa",
    "district": "Lisboa",
    "employmentType": "FULL_TIME",
    "remote": true,
    "industry": "Informática e Tecnologias",
    "jobDescription": "A NLS – New Link Solutions S.A. encontra-se a recrutar um(a) Programador(a) para integrar um projeto no setor público, em regime remoto...",
    "postedDate": "2026-09-01",
    "validThrough": "2026-10-01T23:59:59+00:00",
    "anonymous": false,
    "url": "https://emprego.sapo.pt/offers/programadora?id=c3d28e2c-c37f-4dc1-b3d1-7e87a08b1035",
    "scrapedAt": "2026-09-06T14:14:03.489Z",
    "searchQuery": "programador"
}
```

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

### How much does it cost to scrape emprego.sapo.pt?

This actor is billed per result at Standard tier pricing. A typical run scraping 100 job listings with `fetchFullDescription` enabled takes a couple of minutes — the site has no anti-bot protection and each listing only costs one extra plain HTTP request for the detail page. Your run's usage cost only settles after the run reports SUCCEEDED — checking cost mid-run will undercount it.

For regular monitoring, schedule daily or weekly runs to track new job postings automatically.

### Tips

- **Use Portuguese keywords**: emprego.sapo.pt is a Portuguese-language site. Use Portuguese search terms for best results (e.g., `contabilista` instead of `accountant`).
- **Turn off full descriptions for speed**: If you only need titles, companies and locations, set `fetchFullDescription` to `false` to skip the detail-page fetch entirely.
- **Filter by district**: Filtering by district (e.g., `Lisboa`, `Porto`, `Faro`) narrows results and speeds up scraping.
- **Filter by category**: The 34 available categories help narrow results to relevant sectors without wasting compute on unrelated listings.
- **Schedule recurring runs**: Set up a daily or weekly schedule to build a historical dataset of the Portuguese job market.

### Frequently asked questions

#### Is it legal to scrape emprego.sapo.pt?

This actor extracts publicly available job listing data. It does not access any private, paywalled, or login-protected content. Always review the target website's Terms of Service before scraping, and use the data responsibly and in compliance with applicable laws.

#### Can I scrape jobs from specific Portuguese districts?

Yes. Use the `location` input field with any of Portugal's 20 districts (Lisboa, Porto, Braga, Coimbra, Faro, Aveiro, etc.).

#### What if the scraper returns no results?

- Verify your search query is in Portuguese.
- Try a broader query or remove the district/category filter.
- Very narrow searches (a rare keyword combined with a small district) can genuinely have zero matches on the live site.

#### Can I integrate this with my tools?

Yes. Apify provides API access, webhooks, and direct integrations with tools like Zapier, Make, Google Sheets, and Slack. You can also use the Apify API Client in Python, JavaScript, or any HTTP-capable language.

### Related scrapers

If you need broader coverage of the Portuguese and European jobs market, check out:

- [Net-Empregos Scraper](https://apify.com/studio-amba/net-empregos-scraper) — Portugal's other major general jobs board.
- [Jobnet Scraper](https://apify.com/studio-amba/jobnet-scraper) — Denmark's public employment service job board.
- [Le Forem Scraper](https://apify.com/studio-amba/leforem-scraper) — Wallonia's (Belgium) public employment service job board.

### Maintained by Studio Amba

We run 700+ scrapers for European websites, and the priority is keeping every one of them working. Automated runs test this actor against the live site and verify the output is complete. When the website changes, the scraper usually gets repaired the same day, without you having to report anything. Questions and issues go straight to the people who built it, and most get an answer the same day.

### Need this data on a schedule, or a custom version?

We run this scraper as a managed service for businesses: scheduled runs, deduplication, delta detection, and delivery to your inbox, Google Sheets, or API, maintenance included. We can also build a custom version with your exact fields and filters, or combine multiple sources into one feed.

See [studioamba.dev/services](https://studioamba.dev/services/) or email <hello@studioamba.dev> for a free data sample.

### Support

If you encounter any issues or have feature requests, please open an issue in the **Issues** tab on this actor's page. For custom scraping solutions or enterprise needs, reach out through the Apify platform.

# Actor input Schema

## `searchQuery` (type: `string`):

Job search keyword (e.g. 'programador', 'contabilista', 'enfermeiro'). Defaults to 'emprego' if left empty.

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

Portuguese district to filter by (e.g. 'Lisboa', 'Porto', 'Braga'). Leave empty for all of Portugal.

## `category` (type: `string`):

Filter by job category.

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

Maximum number of job listings to scrape.

## `fetchFullDescription` (type: `boolean`):

When enabled, visits each job's detail page to extract the full description, employment type, industry, and remote-work flag (from the site's own structured JobPosting data). Adds one extra plain HTTP request per result. When disabled, only the short listing snippet is returned.

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

Proxy settings. The site has no anti-bot protection, so the automatic default works well.

## Actor input object example

```json
{
  "searchQuery": "programador",
  "category": "",
  "maxResults": 5,
  "fetchFullDescription": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (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 = {
    "searchQuery": "programador",
    "maxResults": 5,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("studio-amba/emprego-sapo-pt-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 = {
    "searchQuery": "programador",
    "maxResults": 5,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("studio-amba/emprego-sapo-pt-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 '{
  "searchQuery": "programador",
  "maxResults": 5,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call studio-amba/emprego-sapo-pt-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,studio-amba/emprego-sapo-pt-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/7JaKIcIphLCYLs04u/builds/AlPPViS9SAGZLC4dW/openapi.json
