# IEFPOnline Scraper — Portugal Job Listings Data (`studio-amba/iefp-pt-scraper`) Actor

Scrape job listings, locations, salaries, and posting dates from IEFPOnline, Portugal's national public employment service job board. Form-based search plus JSON-LD detail pages, no login.

- **URL**: https://apify.com/studio-amba/iefp-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/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

## IEFPOnline Scraper

Extract **job listings from [IEFPOnline](https://iefponline.iefp.pt/)**, the job board run by Portugal's Instituto do Emprego e Formação Profissional (IEFP), the national public employment service. IEFPOnline is where Portuguese employers register vacancies with the state, so it's a direct read on Portugal's formally-registered job market — not a scrape of a private aggregator's re-listing of the same postings.

This Actor pulls **job titles, locations, posting dates, expiry dates, contract types, salaries, and vacancy counts** by driving IEFPOnline's public search form and reading the clean schema.org structured data embedded on each posting's detail page. No login, no cookies, no browser automation required.

### What does IEFPOnline Scraper do?

Give it a Portuguese keyword (for example `cozinheiro`, `enfermeiro`, `programador`, or `motorista`) and the Actor searches IEFPOnline's job-offer index, paginates through the results, fetches each posting's detail page, and returns clean, structured records you can download as JSON, CSV, Excel, or HTML — or pull through the Apify API into your own systems.

Because it runs on the Apify platform, you also get scheduling, monitoring, proxy rotation, and integrations (webhooks, Make, Zapier, Google Sheets) out of the box.

### Why use IEFPOnline Scraper?

- **State-run registry, not a re-listing.** IEFPOnline is where employers file vacancies with Portugal's public employment service directly — a primary source, not an aggregator of aggregators.
- **Nationwide coverage.** Every Portuguese municipality and district is represented, roughly 6,000+ active job offers at any time.
- **Structured salary data.** Most postings disclose a monthly base salary in EUR, useful for wage-benchmarking research most job boards don't expose.
- **Labour-market research.** Track hiring demand by occupation, region, or sector over time.
- **Recruitment and sourcing.** Build lead lists of sectors and regions actively hiring for a role.
- **Job aggregators.** Feed a niche job site or newsletter with fresh, structured Portuguese listings.
- **No anti-bot headaches.** The public search form has no CAPTCHA and no IP-level blocking, so runs are fast and reliable.

### How to scrape IEFP.pt data

1. Open the Actor and go to the **Input** tab.
2. Enter a **Search Query** in Portuguese (e.g., `cozinheiro`, `enfermeiro`, `motorista`, `programador`).
3. Set **Max Results** to control how many listings you want.
4. Click **Start**. When the run finishes, open the **Output** tab and download your data as JSON, CSV, Excel, or HTML.

That's it. You can also schedule the Actor to run daily and be notified of new listings.

### Input

| Field | Type | Description |
| --- | --- | --- |
| `searchQuery` | string | Portuguese keyword to search for. Defaults to `cozinheiro`. |
| `maxResults` | integer | Maximum number of listings to return (default 100). |
| `proxyConfiguration` | object | Proxy settings. IEFPOnline's search form showed no IP-based blocking during testing, so Apify's automatic proxy works well. |

#### Example input

```json
{
  "searchQuery": "enfermeiro",
  "maxResults": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

### Output

Each job is returned as one dataset record. You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

#### Example output item

```json
{
  "id": "589443099",
  "jobTitle": "Enfermeiro de Cuidados Gerais (M/F)",
  "company": "Empregador não divulgado",
  "locationRaw": "VISEU | Diurno",
  "locationParsed": {
    "city": "Viseu",
    "region": "Viseu",
    "country": "Portugal"
  },
  "language": "pt",
  "postedAt": "2026-08-20T00:00:00.000Z",
  "validThrough": "2026-09-30T00:00:00.000Z",
  "descriptionSnippet": "ENFERMEIRO/A PARA LAR DE IDOSOS",
  "url": "https://iefponline.iefp.pt/IEFP/pesquisas/detalheOfertas2.do?idOferta=589443099&nav=true",
  "employmentType": "FULL_TIME, TEMPORARY",
  "salaryRaw": "1250 EUR/mês",
  "numVacancies": 1,
  "source": "iefp.pt",
  "scrapedAt": "2026-08-20T19:45:00.090Z"
}
```

#### Data fields

| Field | Description |
| --- | --- |
| `id` | Stable IEFPOnline offer ID (used for de-duplication) |
| `jobTitle` | Job posting title |
| `company` | Employer name. Always `"Empregador não divulgado"` — see Limitations |
| `locationRaw` | Location as IEFPOnline lists it: municipality and shift |
| `locationParsed.city` / `.region` / `.country` | Structured location |
| `language` | Always `pt` — IEFPOnline is a Portuguese-only national portal |
| `postedAt` | ISO 8601 date the job was published |
| `validThrough` | ISO 8601 date the posting expires |
| `descriptionSnippet` | Plain-text description / candidate profile, truncated to ~350 characters |
| `url` | Link to the posting's detail page on IEFPOnline |
| `employmentType` | Contract type(s), e.g. `FULL_TIME`, `FULL_TIME, TEMPORARY` |
| `salaryRaw` | Base monthly salary in EUR, when disclosed |
| `numVacancies` | Number of open positions for this posting |
| `source` | Always `iefp.pt` |
| `scrapedAt` | ISO 8601 collection timestamp |

### How much does it cost to scrape IEFP.pt?

The Actor reads a lightweight form-based search plus a small structured-data block per posting, so runs are cheap and fast. A typical run of a hundred listings finishes in well under a minute and uses a small amount of compute. This Actor is billed **pay per result** — you're charged a small fixed cost per result (job posting) plus a per-run start fee, not for compute time. Check the pricing box on the Actor page for the current cost estimate per result. Larger runs simply scale linearly with the number of results.

**Note:** usage cost only settles once a run reports **SUCCEEDED**. If you read the dataset mid-run or after an ABORTED/FAILED run, the item count (and cost) you see is a partial snapshot, not the final total — wait for the run status to flip to SUCCEEDED before reconciling usage.

### Tips and advanced options

- **Portuguese keywords.** The board is Portuguese-only. Use Portuguese job titles for the best coverage (e.g. `motorista`, not `driver`).
- **Deduplication.** Results are de-duplicated by offer ID within a run.
- **Broad queries return the most volume.** Common terms like `cozinheiro`, `assistente`, or `empregado` reliably return hundreds of matching postings nationwide.

### Limitations

- **Employer name isn't disclosed.** IEFPOnline's structured job-posting data always lists the platform itself (`IEFP I.P.`) as the `hiringOrganization`, never the real employer — every national public employment service handles employer privacy a little differently, and this is how Portugal's does it. The Actor returns `"Empregador não divulgado"` for the `company` field rather than the platform's own name, and the rest of the record (title, location, dates, salary, contract type) is still fully populated.
- **Salary is disclosed on most, but not guaranteed on every, posting.** When absent, `salaryRaw` is `null`.
- **No direct external URL for postings.** The link returned is the canonical IEFPOnline detail page, not the original employer's own listing (if one exists elsewhere).

### FAQ, disclaimers, and support

**Is scraping IEFPOnline legal?** This Actor reads a public search form that Portugal's public employment service exposes for its own website. Use the data responsibly and in line with applicable terms and data-protection law. You are responsible for how you use the extracted data.

**Do I need an account or API key?** No. The Actor handles form navigation for you. No login or cookies are required.

**Why is the company field always "Empregador não divulgado"?** See Limitations above — IEFP's structured feed identifies the platform itself, not the hiring company, in every posting sampled.

**Something's not working.** Open an issue on the Actor's **Issues** tab with your input and the run link. Custom fields or a tailored version can also be arranged.

### Related Scrapers

Looking for job data from other European public employment services? Studio AMBA also maintains:

- [SEPE Empléate Scraper](https://apify.com/studio-amba/sepe-scraper) — Spain's state employment service
- [France Travail Scraper](https://apify.com/studio-amba/francetravail-scraper) — France's state employment service
- [VDAB Scraper](https://apify.com/studio-amba/vdab-scraper) — Flanders (Belgium) employment service
- [Le Forem Scraper](https://apify.com/studio-amba/leforem-scraper) — Wallonia (Belgium) employment service
- [Werk.nl Scraper](https://apify.com/studio-amba/werk-nl-scraper) — Netherlands employment service (UWV)
- [Arbeitsagentur Scraper](https://apify.com/studio-amba/arbeitsagentur-scraper) — Germany's Federal Employment Agency
- [Arbetsförmedlingen Scraper](https://apify.com/studio-amba/arbetsformedlingen-scraper) — Sweden's Public Employment Service
- [NAV Scraper](https://apify.com/studio-amba/nav-scraper) — Norway's Labour and Welfare Administration
- [CBOP Poland Scraper](https://apify.com/studio-amba/cbop-poland-scraper) — Poland's Central Job Offers Database

# Actor input Schema

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

Keyword to search for (Portuguese). Examples: 'cozinheiro' (cook), 'enfermeiro' (nurse), 'programador' (developer), 'motorista' (driver). Leave empty to use the default.

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

Maximum number of job listings to return.

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

Proxy settings. IEFPOnline's search form is public and did not show IP-based blocking during testing, so Apify's automatic proxy works well.

## Actor input object example

```json
{
  "searchQuery": "cozinheiro",
  "maxResults": 5,
  "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": "cozinheiro",
    "maxResults": 5,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

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

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,studio-amba/iefp-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/9QNow7Ml9nOAdDJM6/builds/sf8sJadmo27c3H0sY/openapi.json
