# NoFluffJobs Tech Jobs Scraper (`automation-lab/nofluffjobs-tech-jobs-scraper`) Actor

Scrape NoFluffJobs tech jobs, salaries, skills, companies, locations, and detailed requirements across Poland and CEE.

- **URL**: https://apify.com/automation-lab/nofluffjobs-tech-jobs-scraper.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 33.3% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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

## NoFluffJobs Tech Jobs Scraper

Extract public NoFluffJobs vacancies into clean, structured job records with salary ranges, contract types, skills, seniority, locations, requirements, responsibilities, benefits, and source dates.

Use a search you define with filters, a category URL such as `https://nofluffjobs.com/pl/backend`, or one or more individual job URLs. The Actor follows public server-rendered pages and saves one normalized dataset item per accepted vacancy.

### What does NoFluffJobs Tech Jobs Scraper do?

The Actor turns public NoFluffJobs Poland and CEE job pages into integration-ready JSON.

It can:

- discover vacancies from search and category pages;
- process individual NoFluffJobs job URLs;
- paginate through server-rendered search results;
- extract transparent salary amounts, currencies, and periods;
- enrich every result with detail-page requirements and responsibilities;
- filter by keyword, location, country, remote status, seniority, technology, contract type, salary, and currency;
- deduplicate jobs by canonical source URL;
- stop at a user-defined output limit;
- run on schedules for repeat monitoring.

The Actor uses lightweight HTTP requests rather than a browser. No login, cookies, or user account are required for public pages.

### Who is it for?

#### Recruiters and staffing teams

Build focused candidate-market feeds, monitor new roles from target categories, and compare employer demand for specific technologies.

#### Job aggregators

Collect normalized job URLs, titles, companies, locations, salaries, skills, and descriptions for downstream search or matching systems.

#### Compensation analysts

Track advertised salary ranges by technology, seniority, city, currency, period, and contract type.

#### Sales and lead teams

Identify companies currently hiring for relevant technical capabilities and prioritize timely outreach.

#### Labor-market researchers

Create repeatable snapshots of public vacancy, skill, remote-work, and salary signals across NoFluffJobs locales.

### Why use this Actor?

NoFluffJobs listings contain unusually useful salary and technology signals, but their public pages are designed for human browsing rather than recurring data workflows.

This Actor provides:

- a stable typed dataset instead of raw HTML;
- both category discovery and exact job URL processing;
- normalized salary fields instead of one display string;
- mandatory and nice-to-have skills as separate arrays;
- detail enrichment in the same output record;
- consistent filters for both discovered and explicit URLs;
- conservative concurrency and bounded transient retries;
- pay-per-event billing tied to accepted records only.

Jobs rejected by your filters, duplicate links, and failed pages are not charged as item events.

### What data can be extracted?

| Field | Description |
| --- | --- |
| `url`, `slug` | Canonical posting URL and stable source slug |
| `title`, `company` | Job title and hiring organization |
| `companyLogoUrl` | Public company logo URL when exposed |
| `location`, `country`, `remote` | Primary structured location and remote flag |
| `salaryMin`, `salaryMax` | Advertised salary range for the stated period |
| `salaryCurrency`, `salaryPeriod` | Currency and period such as PLN per Hour |
| `employmentTypes` | Structured contract or employment types |
| `category`, `seniority` | Occupational category and experience level |
| `technologies` | Combined technology and skill list |
| `requiredSkills` | Skills marked mandatory |
| `niceToHaveSkills` | Skills marked nice to have |
| `publishedAt`, `expiresAt` | Source publication and expiry dates when available |
| `immediateStart` | Whether the source marks an immediate start |
| `description` | Normalized offer description |
| `requirements` | Detailed requirements text |
| `responsibilities` | Advertised tasks and responsibilities |
| `benefits` | Structured benefits list |
| `applyUrl` | Public application URL when present in server-rendered markup |
| `scrapedAt` | ISO timestamp for the extraction |

Fields can be `null` when NoFluffJobs does not expose that value. In particular, `applyUrl` can be null when the application target is initialized only in the interactive client.

### How to scrape NoFluffJobs jobs

1. Open the Actor in Apify Console.
2. Keep the prefilled backend category URL or remove it to build a filtered search.
3. Add a keyword, location, seniority, technology, or salary filter if needed.
4. Set `maxItems` to the maximum accepted jobs you want.
5. Set `maxPages` to bound search-page inspection.
6. Click **Start**.
7. Open the **Jobs overview** dataset view.
8. Export the records as JSON, CSV, Excel, XML, RSS, or JSONL.

A small first run with 10–20 jobs is recommended before scheduling a larger recurring workflow.

### Input parameters

| Input | Type | Default | Purpose |
| --- | --- | --- | --- |
| `startUrls` | array | backend category prefill | Search, category, or individual job URLs |
| `keyword` | string | optional | Match title, description, requirements, or technologies |
| `locale` | string | `pl` | Locale used for generated searches |
| `category` | string | optional | Category path such as `backend`, `frontend`, or `devops` |
| `location` | string | optional | City or region substring |
| `country` | string | optional | Structured country name or code |
| `remoteOnly` | boolean | `false` | Keep only remote jobs |
| `seniority` | string array | optional | Match any requested seniority |
| `technologies` | string array | optional | Require every requested technology |
| `employmentTypes` | string array | optional | Match any contract or employment type |
| `minSalary` | number | optional | Require the advertised maximum to meet this floor |
| `currency` | string | optional | Require a currency such as `PLN` or `EUR` |
| `maxItems` | integer | `20` | Maximum accepted dataset records |
| `maxPages` | integer | `5` | Maximum pages inspected per listing URL |

Only public HTTPS URLs on `nofluffjobs.com` are accepted. Unsupported domains and malformed filters fail the run instead of silently producing misleading empty output.

### Input examples

#### Search for Python jobs

```json
{
  "keyword": "Python",
  "locale": "pl",
  "maxItems": 20,
  "maxPages": 3
}
```

#### Monitor a category

```json
{
  "startUrls": [
    { "url": "https://nofluffjobs.com/pl/backend" }
  ],
  "seniority": ["Senior"],
  "maxItems": 25,
  "maxPages": 3
}
```

#### Track remote cloud contracts

```json
{
  "startUrls": [
    { "url": "https://nofluffjobs.com/pl/devops" },
    { "url": "https://nofluffjobs.com/pl/backend" }
  ],
  "remoteOnly": true,
  "technologies": ["AWS"],
  "employmentTypes": ["CONTRACTOR"],
  "currency": "PLN",
  "minSalary": 100,
  "maxItems": 50,
  "maxPages": 5
}
```

### Output example

A current public detail-page run produces records shaped like this:

```json
{
  "url": "https://nofluffjobs.com/pl/job/senior-ai-engineer-python-scalo-krakow",
  "slug": "senior-ai-engineer-python-scalo-krakow",
  "title": "Senior AI Engineer (Python)",
  "company": "Scalo",
  "location": "Kraków",
  "country": "POL",
  "remote": false,
  "salaryMin": 145,
  "salaryMax": 155,
  "salaryCurrency": "PLN",
  "salaryPeriod": "Hour",
  "employmentTypes": ["CONTRACTOR"],
  "category": "backend",
  "seniority": "Senior",
  "technologies": ["Python", "API", "Azure", "AI", "Java"],
  "requiredSkills": ["Python", "API", "Azure", "AI"],
  "niceToHaveSkills": ["Java"],
  "publishedAt": "2026-07-22",
  "expiresAt": null,
  "immediateStart": true,
  "responsibilities": ["Design and maintain AI and backend applications"],
  "benefits": ["Sport subscription", "Training budget", "Private healthcare"],
  "applyUrl": null,
  "scrapedAt": "2026-07-27T12:00:00.000Z"
}
```

Long description and requirements fields are shortened above for readability. Dataset records contain the complete normalized text exposed by the source.

### How much does it cost to scrape NoFluffJobs jobs?

The Actor uses pay-per-event pricing:

- **$0.005 per run** for the `start` event;
- **$0.000041071 per accepted job** at the FREE tier;
- lower per-job prices apply automatically at higher Apify billing tiers, down to **$0.00001 per job** at DIAMOND.

Example FREE-tier Actor charges:

| Accepted jobs | Run fee | Item events | Total Actor charge |
| ---: | ---: | ---: | ---: |
| 20 | $0.005 | $0.00082 | $0.00582 |
| 100 | $0.005 | $0.00411 | $0.00911 |
| 1,000 | $0.005 | $0.04107 | $0.04607 |

Only records that pass your filters and are saved to the dataset create `item` events. Platform compute and storage usage may also apply according to your Apify plan.

### Filtering, pagination, and limits

Search/category pages use the source's public `page` parameter. NoFluffJobs returns cumulative server-rendered results on later pages; the Actor deduplicates canonical job URLs before detail requests and output.

Filters are applied after detail normalization, so explicit job URLs and discovered jobs follow the same rules. A narrow filter may require inspecting several pages before the Actor finds `maxItems` accepted jobs.

`maxPages` limits inspection per search URL. `maxItems` limits accepted output across all start URLs. Reaching source exhaustion with fewer matches is a successful result, not an error.

### Scheduling and integration workflows

Useful repeat workflows include:

1. **Daily vacancy feed** — schedule a category run and export new slugs to a database.
2. **Salary benchmark** — group `salaryMin` and `salaryMax` by seniority, currency, period, and technology.
3. **Hiring-intent leads** — alert a sales team when target companies post jobs matching selected skills.
4. **Skills demand tracker** — count required technologies over weekly dataset snapshots.
5. **Remote contract monitor** — combine `remoteOnly`, `employmentTypes`, and a salary floor.
6. **Job aggregation** — map the stable output fields into an ATS, search index, or internal portal.

Use Apify schedules and webhooks to trigger downstream automation after successful runs.

### Use the Actor through the API

Replace `YOUR_TOKEN` with an Apify API token.

#### cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~nofluffjobs-tech-jobs-scraper/runs?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"keyword":"Python","locale":"pl","maxItems":20,"maxPages":3}'
```

#### JavaScript

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/nofluffjobs-tech-jobs-scraper').call({
    keyword: 'Python',
    locale: 'pl',
    maxItems: 20,
    maxPages: 3,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_TOKEN")
run = client.actor("automation-lab/nofluffjobs-tech-jobs-scraper").call(
    run_input={"keyword": "Python", "locale": "pl", "maxItems": 20, "maxPages": 3}
)
items = client.dataset(run["defaultDatasetId"]).list_items().items
print(items)
```

For synchronous API calls, use the run-sync endpoint only when your client timeout comfortably exceeds the Actor timeout.

### Use NoFluffJobs data with MCP

Add this Actor to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/nofluffjobs-tech-jobs-scraper"
```

#### Claude Desktop

Add this server to the Claude Desktop MCP configuration:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/nofluffjobs-tech-jobs-scraper"
    }
  }
}
```

#### Cursor

Use the same JSON under Cursor's MCP settings and restart the MCP connection after saving it.

#### VS Code

Add the same HTTP server URL to your VS Code MCP configuration, then enable the server for the current workspace.

Example prompts:

- “Find 20 current NoFluffJobs Python roles and summarize salary ranges by seniority.”
- “Monitor the backend category for remote contractor roles requiring AWS.”
- “Compare required technologies across the latest NoFluffJobs backend vacancies.”

### Reliability and troubleshooting

#### A run returns fewer jobs than `maxItems`

The source may have fewer matching public jobs, or your filters may be narrow. Increase `maxPages`, broaden filters, or inspect the same category in a browser.

#### A run returns zero jobs

Test with only a real category URL and a small `maxItems`. Then add filters one at a time. Technology filters require every requested value, while seniority and employment type filters match any requested value.

#### A URL is rejected

The Actor intentionally accepts only public HTTPS NoFluffJobs URLs. Remove redirects, tracking wrappers, or third-party URLs.

#### NoFluffJobs returns 403 or 429

The Actor does not silently activate a paid residential proxy. Retry later with a smaller page scope. Persistent source access changes will surface as a failed run rather than false empty data.

#### Salary fields look smaller than monthly values

Always read `salaryPeriod`. Some contracts are advertised per hour; others are monthly. Compare salaries only after grouping by currency and period.

### Limitations

- Public jobs can change or expire between scheduled runs.
- NoFluffJobs may change its SSR markup or structured data.
- `applyUrl` can be null when client-side initialization controls the application flow.
- Salary values preserve the source period and currency; the Actor does not convert currencies or annualize amounts.
- A posting can expose multiple locations or arrangements; the output currently reports the primary structured location.
- No automatic browser or residential proxy fallback is enabled.
- The Actor does not bypass login, CAPTCHA, access controls, or private application forms.
- Search pagination and available filters can vary by locale.

### Responsible use and legality

This Actor extracts information from public NoFluffJobs pages. You are responsible for ensuring that your collection and use comply with NoFluffJobs terms, applicable laws, database rights, privacy obligations, and your organization's policies.

Do not use the output for unlawful discrimination, spam, identity profiling, or attempts to access private candidate or employer data. Collect only what you need, keep snapshots for an appropriate period, and honor valid deletion or correction obligations.

Job descriptions can contain employer-authored content. Preserve source attribution and review redistribution rights before republishing full text.

### Related Automation Lab Actors

No exact same-source companion is required to use this Actor. For broader data workflows, browse the [Automation Lab Apify Store profile](https://apify.com/automation-lab) for currently available business, lead-generation, and job-data Actors.

Related links will remain limited to active Automation Lab Actors so users are not sent to retired or third-party products.

### FAQ

#### Does this Actor require a NoFluffJobs account?

No. It reads public server-rendered search and job detail pages.

#### Can I scrape one exact job?

Yes. Put the public job URL in `startUrls`. All configured filters still apply.

#### Can I scrape several categories?

Yes. Add each real category URL to `startUrls`. Results are deduplicated across all inputs.

#### Are salaries normalized?

Amounts are separated into minimum, maximum, currency, and period fields. The Actor does not perform currency conversion or period conversion.

#### Are filtered-out jobs charged?

No item event is charged for filtered, duplicate, empty, or failed records. A one-time `start` event is charged per run.

#### Can I run it every day?

Yes. Use an Apify schedule and compare `slug`, `publishedAt`, and `scrapedAt` across snapshots.

#### Does it use a proxy?

No automatic proxy mode is included. Direct public SSR access was selected to keep the workflow transparent and economical.

#### How do I export results?

Use the dataset export controls or the Apify API to download JSON, CSV, Excel, XML, RSS, or JSONL.

# Actor input Schema

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

Optional NoFluffJobs search, category, or individual job URLs. Leave empty to build a search from the filters below.

## `keyword` (type: `string`):

Match the job title, description, requirements, or technologies, for example Python or data engineer.

## `locale` (type: `string`):

NoFluffJobs locale used when the Actor builds a search URL.

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

Optional NoFluffJobs category path such as backend, frontend, devops, testing, or data.

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

Keep jobs whose location contains this city or region.

## `country` (type: `string`):

Keep jobs whose structured location country contains this value, such as POL.

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

Keep only postings marked as remote or telecommute.

## `seniority` (type: `array`):

Keep jobs matching any requested level, for example Junior, Mid, or Senior.

## `technologies` (type: `array`):

Keep jobs containing every requested technology or skill.

## `employmentTypes` (type: `array`):

Keep jobs matching any structured employment type, for example CONTRACTOR or FULL\_TIME.

## `minSalary` (type: `number`):

Keep jobs whose maximum advertised salary is at least this amount. Combine with currency for precise analysis.

## `currency` (type: `string`):

Keep jobs with this salary currency code, for example PLN, EUR, or HUF.

## `maxItems` (type: `integer`):

Maximum number of matching job records saved to the dataset.

## `maxPages` (type: `integer`):

Maximum pages inspected per search/category URL. Detail URLs always use one page.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://nofluffjobs.com/pl/backend"
    }
  ],
  "keyword": "Python",
  "locale": "pl",
  "category": "backend",
  "remoteOnly": false,
  "maxItems": 3,
  "maxPages": 1
}
```

# Actor output Schema

## `dataset` (type: `string`):

All accepted job records in the default dataset.

# 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 = {
    "startUrls": [
        {
            "url": "https://nofluffjobs.com/pl/backend"
        }
    ],
    "keyword": "Python",
    "category": "backend",
    "maxItems": 3,
    "maxPages": 1
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/nofluffjobs-tech-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 = {
    "startUrls": [{ "url": "https://nofluffjobs.com/pl/backend" }],
    "keyword": "Python",
    "category": "backend",
    "maxItems": 3,
    "maxPages": 1,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/nofluffjobs-tech-jobs-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "startUrls": [
    {
      "url": "https://nofluffjobs.com/pl/backend"
    }
  ],
  "keyword": "Python",
  "category": "backend",
  "maxItems": 3,
  "maxPages": 1
}' |
apify call automation-lab/nofluffjobs-tech-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=automation-lab/nofluffjobs-tech-jobs-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/pONcjmKKJMLkfc045/builds/r9yGwPQdc8shs5ALS/openapi.json
