# AIJobs.net Scraper (`bovi/aijobs-net-scraper`) Actor

Collect AI and tech job listings from AIJobs.net into structured records. Set maxItems, review fields, and check current pricing before running. Use a residential Apify proxy; no buyer login is required. Pricing: $0.001 per dataset item plus $0.00005 per Actor Start on Free.

- **URL**: https://apify.com/bovi/aijobs-net-scraper.md
- **Developed by:** [Vitalii Bondarev](https://apify.com/bovi) (community)
- **Categories:** Jobs, Lead generation
- **Features:** Limited permissions
- **Stats:** 4 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.97 / 1,000 aijobs.net scrapers

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?

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

## AIJobs.net Scraper

Open AIJobs.net Scraper to extract AI and tech job listings from AIJobs.net into records for recruiting, lead generation, and job-market analysis. On the Free plan, `apify-default-dataset-item` costs $0.001 per scraped result, and `apify-actor-start` costs $0.00005 per event.

- Extract structured job records with titles, companies, salaries, seniority, work types, locations, and remote status
- Build recruiting and lead-generation lists from job identifiers, company names, source URLs, and application URLs when present
- Analyze AI job-market data using salary, location, seniority, skills, roles, and work-type fields
- Download the collected dataset for analysis or another workflow without supplying a buyer API key, cookie, or proxy credential
- Control the collection size with `maxItems`; the residential Apify proxy configuration is required

### What you get

The Actor produces one structured dataset record for each successfully delivered job listing.

| Field | Type | Description |
| --- | --- | --- |
| `title` | string or null | Job title. |
| `id` | string or null | Job identifier. |
| `company` | string or null | Company associated with the listing. |
| `workType` | string or null | Work type shown for the listing. |
| `salary` | string or null | Salary text shown for the listing. |
| `postedAgo` | string or null | Relative posting time shown for the listing. |
| `sourceUrl` | string or null | Job listing URL returned in the record. |
| `scrapedAt` | string | UTC timestamp for the collection. |
| `error` | string or null | Always null in dataset records; detail-page failures are not pushed. |
| `seniority` | string or null | Seniority shown for the listing. |
| `location` | string or null | Location shown for the listing. |
| `is_remote` | boolean | Whether the listing is marked remote. |
| `tasks` | array | Tasks extracted from the listing. |
| `skills` | array | Skills or technology-stack values extracted from the listing. |
| `benefits` | array | Benefits or perks extracted from the listing. |
| `education` | array | Education values extracted from the listing. |
| `roles` | array | Role values extracted from the listing. |
| `regions` | array | Region values extracted from the listing. |
| `countries` | array | Country values extracted from the listing. |
| `states` | array | State values extracted from the listing. |
| `cities` | array | City values extracted from the listing. |
| `apply_url` | string or null | Application URL when one is available. |
| `source` | string | Source label returned in the record. |

Although the Actor is named AIJobs.net Scraper and its code uses AIJobs.net, the fresh-run dataset sample contains `foorilla.com` in `source` and `sourceUrl`; the sample below preserves those values.

### Sample output

This is a shortened record taken from the fresh-run dataset sample. The empty array fields (`tasks`, `skills`, and the other taxonomy fields) mean that no values were returned for those fields in that record.

```json
{
  "title": "Mid-Level Artificial Intelligence (AI) Engineer",
  "id": "4096213",
  "company": "Global Dimensions",
  "workType": "Full Time",
  "salary": "~USD 99K-184K",
  "postedAgo": "20h ago",
  "sourceUrl": "https://foorilla.com/hiring/jobs/mid-level-artificial-intelligence-ai-engineer-updated-per-job-4096213/",
  "scrapedAt": "2026-11-10T15:44:12.225395+00:00",
  "error": null,
  "seniority": "Mid-level",
  "location": "Updated per job",
  "is_remote": false,
  "tasks": [], "skills": [], "benefits": [], "education": [], "roles": [],
  "regions": [], "countries": [], "states": [], "cities": [], "apply_url": null,
  "source": "foorilla.com"
}
```

### Pricing

Pricing is pay per event. On the Free plan, `apify-actor-start` costs $0.00005 per event when the Actor starts, and `apify-default-dataset-item` costs $0.001 per event for one scraped result with all fields. The Actor Start event count depends on Actor memory: one event per GB, with a minimum of one event.

| Plan | Event | Price |
| --- | --- | --- |
| Free | `apify-actor-start` | $0.00005 per event on the Free plan |
| Free | `apify-default-dataset-item` | $0.001 per event on the Free plan |

On the Free plan, 1,000 `apify-actor-start` events cost 1,000 × $0.00005 = $0.05, and 1,000 `apify-default-dataset-item` events cost 1,000 × $0.001 = $1.00. On the Free plan, 10,000 `apify-actor-start` events cost 10,000 × $0.00005 = $0.50, and 10,000 `apify-default-dataset-item` events cost 10,000 × $0.001 = $10.00.

The event `job-record` has no price, so the buyer is not charged for it.

With the minimum one Actor Start event, **1 result = $0.00105 on Free**: $0.00005 for one Actor Start event on Free plus $0.001 for one dataset item on Free. The exact Free-plan result count within the Apify Free plan’s $5 monthly platform usage credit is **4,999 results**.

For this pay-per-event Actor, compute, Apify Proxy traffic including residential traffic, and storage are included in the event prices and paid by the Actor developer. The platform usage option is not paid by the user for this Actor, so there is no separate user charge for that platform usage.

### How to use

1. **Open** the AIJobs.net Scraper Actor page in your Apify account.
2. **Set** `maxItems` to the number of listings you want and keep a residential Apify proxy configuration.
3. **Run** the Actor and wait for listing collection and detail-page processing to finish.
4. **Download** the results from the dataset and use the structured records in your workflow.
5. **Repeat** the run through Apify Schedules, using daily as a starting point for job listings.

Example of the input:

```json
{
  "query": "artificial intelligence",
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "groups": ["RESIDENTIAL"]
  }
}
```

Export the dataset as JSON or CSV, or read it through the Apify dataset API.

### Input parameters

| Parameter | What it does | Default |
| --- | --- | --- |
| `query` | Required by the input schema. The Actor accepts the value but does not read it, so it has no effect on collection. | `"artificial intelligence"` |
| `maxItems` | Converts the value to an integer and stops collecting after the requested number of unique listing cards. The schema minimum is 1; a runtime value of 0 exits cleanly. | `20` |
| `proxyConfiguration` | Supplies the proxy configuration used for listing and detail-page requests. A residential Apify proxy configuration is required; when omitted, the runtime uses the residential default. | {"useApifyProxy":true,"groups":\["RESIDENTIAL"]} |
| `disableUsageStats` | Set to `true` to opt out of the usage statistics described below. | `false` |

### Limits and edge cases

| Condition | What the buyer sees | What to do |
| --- | --- | --- |
| `maxItems` is set to `0` | The Actor exits cleanly without collecting records. | Set a positive integer. The input schema defines a minimum of 1. |
| A listing page returns no job cards | Pagination stops, so the dataset can contain fewer records than `maxItems`. | Check the run output and retry later if you need another collection attempt. |
| A listing page fetch or parse raises an exception | Pagination stops at that page. Listing cards already collected before the error continue to detail processing. | Check the run log and verify the residential proxy configuration. |
| A detail-page fetch or parse fails | The affected record receives an error internally and is not pushed to the dataset; other collected cards continue processing. | Review the run log and retry the run if the missing listing is needed. |
| A detail page lacks a title, company, ID, or source URL | The detail record fails validation and is not pushed. | Retry the run or use the successfully delivered records. |
| A listing has an ID or source URL already seen during the run | The duplicate card is skipped, which can reduce the final count. | Review the unique records returned by the dataset. |
| No proxy configuration is returned | The Actor raises a runtime error instead of scraping over a direct connection. | Provide the residential Apify proxy configuration shown in the input example. |

### FAQ

#### How much does it cost to scrape AIJobs.net?

On the Free plan, the price is $0.001 per `apify-default-dataset-item` event and $0.00005 per `apify-actor-start` event. With the minimum one Actor Start event, 1 result = $0.00105 on Free.

#### Why is my result empty or smaller than `maxItems`?

The Actor stops pagination when a listing page has no cards or when a listing-page fetch or parse fails. Duplicate listing identifiers or source URLs are skipped, and detail-page failures are not pushed as dataset records. Check the run log, confirm the residential proxy configuration, and review the returned records.

#### What happens when a job detail page does not work?

The affected record is not pushed to the dataset when detail collection or required-field validation fails. Records collected successfully before or after that failure can still be delivered.

#### Do I need to provide a login, API key, or proxy credentials?

The documented inputs do not request a buyer API key, cookie, login, or proxy credential. Run the Actor from your own Apify account and provide the residential Apify proxy configuration required by the Actor.

#### Is collecting this public job data legal or allowed?

Although the Actor is named AIJobs.net Scraper, the fresh-run sample contains public job-listing data with `foorilla.com` URLs and source labels. Whether collecting this data is legal or allowed depends on your use case, the source’s terms, and applicable law, so review those requirements before using the results.

### Related actors

- [AI/ML Hiring Signal Monitor — Track Companies Scaling AI Teams](https://apify.com/bovi/ai-ml-hiring-signal-monitor) — related Actor for tracking companies scaling AI teams.
- [Kariyer.net Scraper — Turkey Job Listings](https://apify.com/bovi/kariyer-net-scraper) — another job-listings Actor focused on Turkey.
- [Ashby Jobs API Scraper — Salary Ranges, Seniority, No Login](https://apify.com/bovi/ashby-job-scraper) — related job scraper with salary ranges and seniority data.

### Usage statistics

This Actor creates a small, content-free summary at the end of each run, used only to monitor reliability and improve this Actor. No input values, credentials or scraped data are sent.

A copy of the exact record for your run is saved as `USAGE_STATS` in your own Apify key-value store.

To opt out, set `disableUsageStats` to `true` in the input. Nothing is sent then.

[Full list of collected fields](https://api.apify.com/v2/key-value-stores/v9rgHjMKLDGtHf8tD/records/index.html)

# Actor input Schema

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

Maximum number of job listings to scrape.

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

The residential Apify proxy is required.

## `disableUsageStats` (type: `boolean`):

See the README Usage statistics section for details.

## Actor input object example

```json
{
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "groups": [
      "RESIDENTIAL"
    ]
  },
  "disableUsageStats": false
}
```

# Actor output Schema

## `results` (type: `string`):

Dataset with the scraped records.

# 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 = {
    "proxyConfiguration": {
        "useApifyProxy": true,
        "groups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("bovi/aijobs-net-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 = { "proxyConfiguration": {
        "useApifyProxy": True,
        "groups": ["RESIDENTIAL"],
    } }

# Run the Actor and wait for it to finish
run = client.actor("bovi/aijobs-net-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 '{
  "proxyConfiguration": {
    "useApifyProxy": true,
    "groups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call bovi/aijobs-net-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bovi/aijobs-net-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/TAp924oqHaefKHSPo/builds/eEofZB2znuUqj4ehQ/openapi.json
