# jobs.at Scraper - Austrian Jobs, Salary & Source (`aidnurs/jobs-at-scraper`) Actor

Scrape jobs.at, Austria's job search engine, as an API: salary min/max/period with 14 payments, employment type, home office, company, full description and the original job link (karriere.at, hokify.at, company career pages). Only new jobs mode. Duplicates are free.

- **URL**: https://apify.com/aidnurs/jobs-at-scraper.md
- **Developed by:** [Nursultan Imanov](https://apify.com/aidnurs) (community)
- **Categories:** Jobs, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 jobs

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

### jobs.at scraper and jobs.at API

**jobs.at Jobs Scraper** extracts job listings from [jobs.at](https://www.jobs.at), one of Austria's big job search engines. jobs.at collects ads posted directly on the site plus thousands of jobs from partner boards and company career pages, so one search covers a large part of the Austrian job market.

Search by keyword and location, filter by employment type, job level, job field, home office and posting date, and get clean, structured data: **title, company, salary (parsed into min / max / period), employment type, job field, home office flag, posting date, address, the original job link and the full job description**.

Use it as a **jobs.at API** for job market research, recruiting, salary benchmarking, lead generation for HR services, or to build your own job alerts.

### Why use this jobs.at scraper?

- ✅ **Built for reliability.** The Actor reads the same JSON data the jobs.at website uses, not fragile page layouts. No browser, retries with backoff, and it stops cleanly at the end of the results.
- 💶 **Salary as numbers.** Every salary comes as `salaryMin`, `salaryMax`, `salaryPeriod` (`MONTH`, `YEAR`, `HOUR`), plus payments per year (usually 14 in Austria) and weekly hours.
- 🔗 **Original job link.** Most jobs on jobs.at come from other sites. You get `originalUrl` and `originalSite` (e.g. `karriere.at`, `hokify.at`, company career pages) with tracking parameters removed.
- 🔁 **No duplicates charged.** Every job appears once per run. Jobs repeated across search pages are skipped, not billed.
- 🔔 **Only new jobs since the last run.** Turn on *Only new jobs* and schedule the Actor: each run returns just the postings you have not received yet. Perfect for daily job alerts.
- 📄 **Full description** from the job page (optional), plus the original posting date, street address, city and region where the ad provides them.
- 🛡️ **GDPR-friendly by default.** Phone numbers, personal e-mails and contact-person names are masked or left out (role mailboxes like `jobs@` stay). Turn on *Include personal data* only if you have a legal basis.
- ⚡ **Fast and cheap.** Pure HTTP, no proxy needed. 50 jobs with full descriptions take about 10 seconds.

### How much does it cost to scrape jobs.at?

You pay only for jobs saved to the dataset (pay per result). Empty searches cost nothing, and you can cap spending with *Max jobs* and the run's maximum cost.

### How to scrape jobs.at

1. Enter **Keywords** (e.g. `Data Engineer`, `Buchhaltung`) or leave empty for all jobs.
2. Enter a **Location** (`Wien`, `Graz`, `Oberösterreich`) or leave empty for all of Austria.
3. Optionally choose employment types, job levels, job fields, *Posted within* or *Home office only*.
4. Set **Max jobs** and click **Start**.
5. Download the results as JSON, CSV, Excel or HTML, or get them via the Apify API.

### Input example

```json
{
  "keywords": "python",
  "location": "Wien",
  "maxItems": 100,
  "includeDetails": true,
  "employmentTypes": ["Vollzeit"],
  "postedWithin": "7d",
  "homeOfficeOnly": false,
  "onlyNewJobs": false
}
```

### Output example

```json
{
  "id": "7906137",
  "url": "https://www.jobs.at/i/7906137",
  "title": "Software Developer - Odoo / Python (m/w/d)",
  "companyName": "Ventureal Projekt GmbH",
  "companyUrl": "https://www.jobs.at/a/ventureal-projekt",
  "companyAddress": "Laurenzerberg 5/33b, 1010 Wien",
  "location": "Wien",
  "isHomeOffice": true,
  "employmentTypes": ["Vollzeit"],
  "jobFields": ["IT, Software & Telekommunikation"],
  "salaryText": "ab 55.000 € jährlich",
  "salaryMin": 55000,
  "salaryMax": null,
  "salaryCurrency": "EUR",
  "salaryPeriod": "YEAR",
  "salaryPaymentsPerYear": 14,
  "weeklyHours": 38.5,
  "summary": "Du entwickelst und passt Odoo-Module an, integrierst Systeme und übernimmst Testing und Dokumentation. ...",
  "listedAt": "2026-10-01T13:07:11+00:00",
  "datePosted": "2026-10-01",
  "isDirectAd": false,
  "originalUrl": "https://www.karriere.at/jobs/10034449",
  "originalSite": "karriere.at",
  "descriptionText": "Software Developer - Odoo / Python (m/w/d) ...",
  "source": "jobs.at",
  "scrapedAt": "2026-10-07T12:12:36Z"
}
```

### Fields you get

| Field | Description |
|---|---|
| `title`, `url`, `id` | Job title, jobs.at job page and job ID |
| `companyName`, `companyId`, `companyUrl`, `companyLogo`, `companyAddress` | Employer data (company page on jobs.at, business address) |
| `location`, `street`, `postalCode`, `city`, `region`, `country` | Where the job is (address fields when the ad provides them) |
| `salaryText`, `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod` | Salary as text and as numbers |
| `salaryPaymentsPerYear`, `weeklyHours` | Number of salary payments per year and weekly working hours |
| `salaryValueFromPosting`, `salaryUnitFromPosting` | Salary as stated in the job page's structured data (when available) |
| `employmentTypes`, `employmentTypeCodes`, `jobFields` | Vollzeit, Teilzeit, ..., schema.org codes and professional fields |
| `isHomeOffice`, `isDirectAd` | Home office possible; ad posted directly on jobs.at |
| `originalUrl`, `originalSite`, `applyEmail` | Where the job was originally published; role apply mailbox for direct ads |
| `directApply`, `referenceCode` | Whether you can apply directly on the page; employer's reference number |
| `listedAt`, `datePosted`, `validThrough` | Date jobs.at lists the job, original posting date, expiry |
| `summary`, `descriptionText`, `descriptionHtml` | Short summary and full description |
| `source`, `searchUrl`, `scrapedAt` | Source site, the search page the job was found on, scrape time |

### FAQ

**Is it legal to scrape jobs.at?**
This Actor collects only publicly available job postings, the same pages any visitor sees. It never logs in, never uses accounts or cookies of real users, and never solves or bypasses CAPTCHAs.

**Personal data is off by default.** Phone numbers and personal e-mails inside job texts are masked (role mailboxes like `jobs@` or `office@` stay), and contact-person names, direct phones and e-mails are not saved. Names that an employer writes into the free text of a description can still appear as published.

If you turn on **Include personal data**, you get everything the site shows publicly, including the contact person's name, phone and e-mail where available. Personal data is protected by the GDPR in the EU and by similar laws elsewhere. Only enable it if you have a legal basis (for example, a documented legitimate interest), keep only what you need, and do not use it for unsolicited marketing. If you are unsure, consult a lawyer.

You are responsible for how you use the data and for complying with applicable laws and jobs.at's terms. This Actor is not affiliated with or endorsed by jobs.at. Read more: [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/)

Found something that should not be here? Open an issue on the Actor's Issues tab and we will look at it promptly.

**Why do I get fewer jobs than the number jobs.at shows?**
For keyword searches jobs.at shows an estimated total but only lists the relevant results. The Actor returns everything the website itself lists for your search. Very broad searches are limited by jobs.at to 6,000 jobs (400 pages); split them by location or job field to get more.

**Do I need a proxy?**
No. jobs.at works without a proxy. For very large or frequent runs you can add Apify Proxy or your own proxies in the *Advanced* section.

**How do I get only new jobs every day?**
Turn on *Only new jobs since last run*, save the task and add a schedule. Use a different *Monitoring key* for each saved search.

**Something broke or a field is missing?**
Open an issue on the Issues tab. We usually respond within 24 hours.

# Actor input Schema

## `keywords` (type: `string`):

What to search for: job title, skill or company ("Data Engineer", "Buchhaltung", "Billa"). Leave empty for all jobs.

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

City, district or federal state in Austria, e.g. "Wien", "Linz", "Oberösterreich". Leave empty for all of Austria.

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

Maximum number of jobs to save. You only pay for jobs saved to the dataset.

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

Open every job page to add the full description (and exact address and posting date where the ad provides them).

## `includePersonalData` (type: `boolean`):

Off by default: phone numbers and personal e-mails inside job texts are masked (\[phone removed], \[email removed]; role mailboxes like jobs@ or office@ stay), and contact-person names, direct phones and e-mails are not saved.<br><br>Turn it on to get everything the site shows publicly, including the contact person's name, phone and e-mail where the employer published them.<br><br>⚠️ This returns personal data. You're responsible for having a legal basis to collect and use it under privacy laws (e.g. GDPR).

## `homeOfficeOnly` (type: `boolean`):

Only jobs where jobs.at marks home office as possible.

## `postedWithin` (type: `string`):

Only jobs published within this period.

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

Filter by employment type (Anstellungsart).

## `jobLevels` (type: `array`):

Filter by seniority (Positionsebene).

## `jobFields` (type: `array`):

Filter by professional field (Berufsfelder).

## `onlyNewJobs` (type: `boolean`):

Remember job IDs between runs and return only jobs you have not received yet. Ideal for scheduled runs and job alerts. Already-seen jobs are never charged.

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

Name of the memory used by 'Only new jobs'. Use a different key for each saved search.

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

jobs.at works without proxy. Use your own or Apify Proxy if you run very large or frequent scrapes.

## Actor input object example

```json
{
  "keywords": "python",
  "location": "Wien",
  "maxItems": 20,
  "includeDetails": true,
  "includePersonalData": false,
  "homeOfficeOnly": false,
  "postedWithin": "any",
  "onlyNewJobs": false,
  "stateKey": "default",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Scraped job listings (table view).

## `jobsFull` (type: `string`):

All fields including full 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 = {
    "keywords": "python",
    "location": "Wien",
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("aidnurs/jobs-at-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 = {
    "keywords": "python",
    "location": "Wien",
    "maxItems": 20,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("aidnurs/jobs-at-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 '{
  "keywords": "python",
  "location": "Wien",
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call aidnurs/jobs-at-scraper --silent --output-dataset

```

## MCP server setup

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