# Ams Job Search Extractor (`kawsar/ams-job-search-extractor`) Actor

AMS job scraper that searches jobs.ams.at by keyword and returns every matching Austrian vacancy as structured data, with company, location, and full description, so recruiters and job boards can collect listings without hitting the portal token wall.

- **URL**: https://apify.com/kawsar/ams-job-search-extractor.md
- **Developed by:** [Kawsar](https://apify.com/kawsar) (community)
- **Categories:** Jobs, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.99 / 1,000 results

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

## AMS Job Search Extractor: Scrape Austrian Job Listings from jobs.ams.at

AMS Job Search Extractor pulls job listings from Austria's public employment service portal, jobs.ams.at, and returns them as clean, structured data. Give it a keyword and it collects every matching vacancy, along with the company, working location, working hours, education requirements, and the full job description. It is a practical way to scrape AMS Austria jobs for recruitment, market research, and job board data without copying anything by hand.

The AMS search API is guarded by short-lived signed tokens, so a plain HTTP request just returns a 401. This actor loads the real search page in a headless browser and lets the site sign its own API calls, so you get the same job data a normal visitor sees, page after page.

### Use cases

- **Job board aggregation**: pull fresh Austrian vacancies into your own job board or listings app
- **Recruitment sourcing**: find candidates' target roles by keyword, region, and offer type
- **Labor market research**: track which roles, skills, and employers are hiring across Austria
- **Salary and skills analysis**: mine full job descriptions for required qualifications and benefits
- **Lead generation**: build a list of companies actively hiring in a given field
- **Green jobs tracking**: filter for listings AMS flags as green jobs

### Input

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `query` | string | `Engineer` | Keyword to search for, such as a job title, skill, or field. Required. |
| `jobOfferTypes` | array | all types | Offer sources to include, one code per line: BA, BZ, IJ, SB\_WKO, TN. Leave empty for all. |
| `sortOrder` | string | `desc` | Sort direction, descending or ascending. |
| `sortField` | string | `_SCORE` | Portal sort field. Keep as `_SCORE` (relevance) unless you know the internal codes. |
| `maxItems` | integer | `100` | Maximum listings to collect per run, from 1 to 1000. |
| `includeDescriptionHtml` | boolean | `false` | Also keep the original HTML of each description. |
| `timeoutSecs` | integer | `300` | Time budget before the run stops with whatever it has collected. |
| `proxyConfiguration` | object | Datacenter (Anywhere) | Proxy type and location for requests. Supports Datacenter, Residential, Special, and custom proxies. Optional. |

#### Example input

```json
{
    "query": "Engineer",
    "jobOfferTypes": ["BA", "BZ", "IJ", "SB_WKO", "TN"],
    "sortOrder": "desc",
    "maxItems": 100,
    "includeDescriptionHtml": false,
    "proxyConfiguration": { "useApifyProxy": true }
}
```

### What data does this actor extract?

The actor stores results in a dataset. Each entry is one job listing:

```json
{
    "jobId": 22090383,
    "uuid": "57146a03-f614-3a87-8942-e91a3a7b32f7",
    "jobTitle": "COMPLIANCE ENGINEER / CE ENGINEER",
    "companyName": "Felder KG",
    "companyWebsite": null,
    "jobOfferType": "Arbeitsmarktservice",
    "jobOfferTypeCode": "AMS",
    "workingTime": "Vollzeit",
    "employmentRelationship": "ArbeiterInnen/Angestellte",
    "educationLevels": ["Fachhochschule/Universität/pädagogische Hochschule"],
    "occupations": ["MaschinenbautechnikerIn", "ElektroenergietechnikerIn"],
    "countryCode": "AT",
    "federalState": "Tirol",
    "zipCode": "6060",
    "town": "Hall in Tirol",
    "street": "KR-Felder-Straße 1",
    "latitude": 47.27813351,
    "longitude": 11.478667903,
    "isGreenJob": true,
    "lastUpdatedAt": "2026-07-30T00:00:00Z",
    "applicationUrl": "https://felder-group.jobs/de/jobs/compliance_engineer__ce_engineer_mwd_j4746836",
    "descriptionText": "Deine Aufgaben: Sicherstellung der Konformität unserer Maschinen ...",
    "scrapedAt": "2026-08-11T09:00:00Z"
}
```

| Field | Type | Description |
|-------|------|-------------|
| `jobId` | integer | AMS internal numeric ID for the listing. |
| `uuid` | string | Stable UUID of the job offer. |
| `jobTitle` | string | Title of the job listing. |
| `companyName` | string | Hiring company or organization. |
| `companyWebsite` | string | Company home page. AMS rarely fills this field, so the actor falls back to the company link found in the job description when one is present. |
| `jobOfferType` | string | Readable source of the offer, such as Arbeitsmarktservice. |
| `jobOfferTypeCode` | string | Short source code (AMS, BA, BZ, IJ, SB\_WKO, TN). |
| `workingTime` | string | Working time model, such as Vollzeit or Teilzeit. |
| `employmentRelationship` | string | Type of employment relationship. |
| `educationLevels` | array | Required or preferred education levels. |
| `occupations` | array | AMS occupation categories for the role. |
| `countryCode` | string | ISO country code of the working location (usually AT). |
| `federalState` | string | Austrian federal state of the working location. |
| `zipCode` | string | Postal code of the working location. |
| `town` | string | Town or municipality. |
| `street` | string | Street address, when provided. |
| `latitude` | number | Latitude of the working location. |
| `longitude` | number | Longitude of the working location. |
| `isGreenJob` | boolean | Whether AMS flags the role as a green job. |
| `lastUpdatedAt` | string | Date the listing was last updated. |
| `applicationUrl` | string | External company or application link found in the description. |
| `descriptionText` | string | Full description as clean plain text. |
| `descriptionHtml` | string | Original HTML of the description (only with the HTML option on). |
| `scrapedAt` | string | UTC time the listing was collected. |

### How it works

1. You enter a search keyword and, optionally, which offer types to include.
2. The actor opens the AMS search page for that query in a headless browser, one time.
3. The AMS app signs and sends its own search request, and the actor captures the JSON response.
4. It moves through the result pages by clicking next, so the app stays loaded and each page comes back in about a second, until it reaches your `maxItems` limit or the last page.
5. Each listing is cleaned into a flat record and saved to the dataset.

### FAQ

**Why does the actor use a browser instead of calling the API directly?**
The AMS search API rejects unsigned requests with a 401. The token that unlocks it is generated in the browser and tied to each exact request, so the reliable way to get data is to let the real page do the signing. That is what this actor does.

**Do I need to provide any tokens or API keys?**
No. There are no keys, tokens, or logins to set up. You enter a keyword and run it.

**Can it search in German?**
Yes. AMS is an Austrian portal, so most listings are in German. Search with German keywords like `Softwareentwickler` or `Pflege` for the best coverage, and English terms like `Engineer` also return results.

**How many jobs can it collect per run?**
Up to 1000 per run via `maxItems`. Raise or lower it to balance coverage against run time and cost.

**Why is `companyWebsite` sometimes empty?**
AMS itself rarely stores a company website, on both its search and detail data. When it is missing, the actor looks for the company link inside the job description and uses that. If the description has no company link either, the field stays empty, and you can still use `applicationUrl` to reach the role.

**Are the job descriptions cleaned up?**
Yes. Each listing includes a plain-text description with the HTML removed. Turn on `includeDescriptionHtml` if you also want the original markup.

### Integrations

Connect AMS Job Search Extractor with other apps and services using [Apify integrations](https://apify.com/integrations). You can integrate with Make, Zapier, Slack, Airbyte, GitHub, Google Sheets, Google Drive, and many more. You can also use [webhooks](https://docs.apify.com/integrations/webhooks) to trigger actions whenever results are available.

Ready to scrape AMS Austria jobs by keyword? Set a query, pick your offer types, and run the actor to get structured Austrian job listings you can filter, analyze, or feed into your own product.

# Actor input Schema

## `query` (type: `string`):

The job title, skill, or keyword to search for on jobs.ams.at (for example: Engineer, Softwareentwickler, Pflege, Marketing).

## `jobOfferTypes` (type: `array`):

Which job offer sources to include. Enter one code per line. Valid codes: BA (AMS jobs), BZ (AMS training positions), IJ (partner job boards), SB\_WKO (WKO business register), TN (apprenticeships). Leave empty to include all types.

## `sortOrder` (type: `string`):

Order of the results by the sort field.

## `sortField` (type: `string`):

Field the AMS portal sorts by. Leave as \_SCORE (relevance) unless you know the portal's internal field codes.

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

Maximum number of job listings to collect in a single run. Keeps runs fast and affordable.

## `includeDescriptionHtml` (type: `boolean`):

Also store the original HTML of each job description alongside the clean plain-text version.

## `timeoutSecs` (type: `integer`):

Overall time budget for the run before it stops gracefully with whatever has been collected.

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

Select proxies to use for requests. Helps avoid IP blocking and rate limits. Datacenter proxies are fastest; Residential proxies are harder to detect.

## Actor input object example

```json
{
  "query": "Engineer",
  "jobOfferTypes": [
    "BA",
    "BZ",
    "IJ",
    "SB_WKO",
    "TN"
  ],
  "sortOrder": "desc",
  "sortField": "_SCORE",
  "maxItems": 100,
  "includeDescriptionHtml": false,
  "timeoutSecs": 300,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

All scraped job listings in the default dataset.

## `runLog` (type: `string`):

Live log of the current 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 = {
    "query": "Engineer",
    "jobOfferTypes": [
        "BA",
        "BZ",
        "IJ",
        "SB_WKO",
        "TN"
    ],
    "maxItems": 100,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("kawsar/ams-job-search-extractor").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 = {
    "query": "Engineer",
    "jobOfferTypes": [
        "BA",
        "BZ",
        "IJ",
        "SB_WKO",
        "TN",
    ],
    "maxItems": 100,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("kawsar/ams-job-search-extractor").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 '{
  "query": "Engineer",
  "jobOfferTypes": [
    "BA",
    "BZ",
    "IJ",
    "SB_WKO",
    "TN"
  ],
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call kawsar/ams-job-search-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,kawsar/ams-job-search-extractor"
        }
    }
}

```

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/Hn7eemjxvg8b8kjtc/builds/5vp3eULNrA3PxOV7l/openapi.json
