# Avature Crawler (`jobsapi/avature-jobs-search-scraper`) Actor

Crawls public Avature tenant job listings and detail pages with bounded search, single, and multiple modes.

- **URL**: https://apify.com/jobsapi/avature-jobs-search-scraper.md
- **Developed by:** [Jobs API](https://apify.com/jobsapi) (community)
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.99 / 1,000 avature career roles

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## Avature Jobs Search Scraper

### What does Avature Jobs Search Scraper do?

**Avature Jobs Search Scraper** collects rich, public job listings from Avature-hosted career portals. It is a bounded HTML crawler for Avature careers, `SearchJobs`, and `JobDetail` pages, with optional detail-page enrichment.

The Actor reads the public listing page, follows the tenant's exposed pagination links, and fetches public detail pages for complete records. It does not log in, submit applications, use credentials, solve CAPTCHAs, bypass access controls, or collect private profile data. Requests stay on the public Avature tenant host supplied in the input.

### Why use Avature Jobs Search Scraper?

Use the Actor for public job-market research, recruiting pipelines, skills and salary analysis, employer monitoring, career-site catalogs, and downstream search or matching systems.

Main capabilities:

- Rich job rows with stable Avature job identity, title, company, location, business area, department, reference number, employment type, and experience level.
- Full visible detail text plus sanitized HTML, paragraphs, list items, semantic sections, headings, subheadings, section links, responsibilities, qualifications, benefits, compensation, work-model, application, and legal text.
- Visible salary extraction with currency, minimum and maximum values, period, original salary text, and the source of the salary value. Salary is omitted when the page does not publish one.
- Skills, languages, education requirements, experience requirements, contact emails, application links, application provider, company links, public media, video URLs, canonical links, and source provenance.
- Multiple public tenant URLs, direct single-job and multiple-job modes, bounded pagination, global item limits, detail-request limits, total-request limits, polite request delays, and bounded retries.
- Strict dataset and input schemas, source HTML/content hashes, run summaries, health state, structured diagnostics, and per-attempt request receipts.
- Explicit access-stop behavior: HTTP 401, 403, 429, or 451 and visible verification/security challenges stop requests and discard buffered job rows. Receipts and diagnostics are preserved with `resultStatus: SKIPPED`; generic network failures use `resultStatus: DEFERRED`.

### What data can Avature Jobs Search Scraper extract?

Fields are emitted when the public tenant publishes them. A complete job row always has a verified Avature identity, title, company, location, substantive detail description, canonical job URL, and request provenance.

| Group | Fields | Description |
|---|---|---|
| Identity | `id`, `jobId`, `recordId`, `recordType`, `recordStatus` | Stable Avature job identity and complete-record marker. `recordId` has the form `avature-<jobId>`. |
| Core job data | `title`, `company`, `location`, `locations`, `businessArea`, `department`, `referenceNumber`, `employmentType`, `jobType`, `experienceLevel` | Public listing and detail fields. |
| Description | `description`, `descriptionHtml`, `descriptionParagraphs`, `descriptionListItems`, `descriptionTextLength` | Visible detail text, sanitized HTML, paragraphs, lists, and length. |
| Structured description | `descriptionSections`, `descriptionHeadings`, `descriptionSubheadings`, `overviewText`, `responsibilities`, `responsibilityText`, `qualificationItems`, `requirementsText`, `benefitItems`, `benefitsText`, `compensationText`, `workModelText`, `applicationText`, `legalText` | Heading-aware sections and extracted text/list items. Empty source sections are omitted. |
| Requirements | `educationRequirements`, `educationRequirementsList`, `experienceRequirements`, `experienceRequirementsList`, `skills`, `languages`, `contactEmails` | Requirements and useful normalized matches from the public detail text. |
| Location and work | `locationDetails`, `remote`, `hybrid`, `workMode` | Published location details and conservative remote/hybrid signals. |
| Salary | `salary`, `salaryLabel`, `publishedSalaryText`, `salaryText`, `salaryCurrency`, `salaryPeriod`, `salaryMin`, `salaryMax`, `salarySource` | Visible salary data only; no currency conversion or inferred salary. |
| Applications | `applicationUrl`, `applicationLink`, `applicationLinks`, `applicationLinkDetails`, `applicationProvider` | Public application URLs when the tenant publishes them. Save-job links are excluded. |
| Links and media | `contentLinks`, `companyLinks`, `sourceLinks`, `media`, `mediaUrls`, `mediaCount`, `videoUrls` | Public source, company, description, image, video, and application links. |
| Source fields | `sourceRecord`, `sourceFields`, `fieldValues`, `metaTags`, `unlabeledContent` | Raw or normalized labeled Avature values retained for auditability. |
| Provenance | `actorName`, `actorVersion`, `jobUrl`, `canonicalUrl`, `listUrl`, `sourceUrl`, `sourceFinalUrl`, `sourceWebsite`, `sourceDomain`, `sourceEndpoint`, `sourceMode`, `sourceHtmlHash`, `contentHash`, `scrapedAt` | Actor identity, public source URLs, source mode, timestamp, and content hashes for downstream use. |
| Counts and flags | `locationCount`, `descriptionSectionCount`, `descriptionHeadingCount`, `descriptionItemCount`, `responsibilityCount`, `requirementCount`, `qualificationCount`, `educationRequirementCount`, `experienceRequirementCount`, `languageRequirementCount`, `benefitCount`, `skillCount`, `keywordCount`, `applicationLinkCount`, `contactEmailCount`, `hasDescriptionHtml`, `hasDescriptionLists`, `hasApplicationAction`, `hasCompanyProfile`, `hasSalary`, `hasStructuredData` | Explicit coverage counts and booleans for reliable downstream filtering. |
| Run state | `recordStatus`, `dataAvailable`, `found`, `accessStatus`, `extractionMethod` | Concise status, discovery, and extraction context. |

### How to scrape Avature jobs

1. Open the Actor's **Input** tab.
2. Provide a public Avature careers or `SearchJobs` URL in `startUrls`, or use `jobUrl`/`jobUrls` for direct public `JobDetail` pages.
3. Set the page, item, detail, request, timeout, retry, and delay limits.
4. Keep `includeDetails` enabled when you need the rich fields shown above.
5. Start the Actor and open the **Dataset** tab after the run completes.
6. Download the dataset or use the Actor's API and key-value-store run summary in another workflow.

### Input

See the **Input** tab for the validated configuration. The default smoke-test input starts at Bloomberg's public Avature careers portal, fetches up to two listing pages, emits up to ten jobs, and enriches public detail pages.

#### Input sources and modes

| Field | Type | Default | Description |
|---|---|---:|---|
| `mode` | enum | `startUrls` | Accepted values: `startUrls`, `search`, `searchMultiple`, `single`, or `multiple`. Direct modes use `jobUrl`/`jobUrls`; URL-list modes use `startUrls`. |
| `startUrls` | array of objects | Bloomberg careers URL | Public Avature careers, `SearchJobs`, or `JobDetail` URLs. Each item is `{ "url": "https://..." }`; up to 20 URLs are accepted. |
| `jobUrl` | string | not set | One public Avature `JobDetail` URL for `single` mode. |
| `jobUrls` | array of objects | not set | Public Avature `JobDetail` URLs for `multiple` mode. |

The crawler follows only absolute HTTP(S) URLs on the supplied public tenant host. It preserves the tenant's public pagination URLs and does not invent records when no usable public details are available.

#### Pagination, enrichment, and resource limits

| Field | Type | Default | Valid range | Description |
|---|---|---:|---:|---|
| `maxPages` | integer | `2` | `1`–`50` | Maximum listing pages processed across the run. |
| `maxItems` | integer | `10` | `1`–`200` | Maximum complete job records emitted across all supplied URLs. |
| `maxDetailRequests` | integer | `25` | `0`–`200` | Maximum public detail pages fetched. `0` disables detail requests. |
| `maxRequests` | integer | `80` | `1`–`250` | Maximum total public HTTP requests, including listing and detail requests. |
| `includeDetails` | boolean | `true` | — | Fetch public `JobDetail` pages for rich extraction. |
| `timeoutMs` | integer | `30000` | `5000`–`120000` | Timeout for each public HTTP request. |
| `requestDelayMs` | integer | `250` | `0`–`30000` | Polite delay before each public request. Use a conservative value for production runs. |
| `maxRetries` | integer | `2` | `0`–`3` | Retries for transient HTTP failures and request errors. |

The limits are enforced globally. A detail page is counted only after a successful response and a record is emitted only after the required identity, location, company, and description checks pass.

### Input examples

#### 1. Rich tenant search

```json
{
  "startUrls": [
    { "url": "https://bloomberg.avature.net/careers" }
  ],
  "maxPages": 2,
  "maxItems": 10,
  "includeDetails": true,
  "maxDetailRequests": 10,
  "maxRequests": 20,
  "timeoutMs": 30000,
  "requestDelayMs": 500,
  "maxRetries": 2
}
```

#### 2. One public job detail page

```json
{
  "mode": "single",
  "jobUrl": "https://bloomberg.avature.net/careers/JobDetail/Portfolio-PORT-Enterprise-Sales-Executive-Financial-Solutions/44905",
  "includeDetails": true,
  "maxItems": 1,
  "maxDetailRequests": 1,
  "maxRequests": 1,
  "requestDelayMs": 250,
  "maxRetries": 2
}
```

#### 3. Several public job detail pages

```json
{
  "mode": "multiple",
  "jobUrls": [
    { "url": "https://example.avature.net/careers/JobDetail/Example-Role/1001" },
    { "url": "https://example.avature.net/careers/JobDetail/Another-Role/1002" }
  ],
  "maxItems": 2,
  "maxDetailRequests": 2,
  "maxRequests": 2
}
```

#### 4. Multiple tenant entry points

```json
{
  "mode": "searchMultiple",
  "startUrls": [
    { "url": "https://bloomberg.avature.net/careers" },
    { "url": "https://jobs.example.org/SearchJobs" }
  ],
  "maxPages": 1,
  "maxItems": 20,
  "includeDetails": true,
  "maxDetailRequests": 8,
  "requestDelayMs": 1000
}
```

### Output

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

The default dataset contains complete public job records. It does not mix run summaries into the job dataset. Run state is written to the default key-value store under `OUTPUT`, `OUTPUT_SUMMARY`, `DIAGNOSTICS`, `RUN_HEALTH`, and `REQUEST_RECEIPTS`. Receipts include the requested/final URL, attempt number, status, response hash, timing, and outcome, without storing the response body.

#### Representative rich dataset item

The following is a shortened example. Array lengths and optional fields vary by Avature tenant and by what the public page publishes.

```json
{
  "recordType": "job",
  "recordStatus": "complete",
  "id": "44905",
  "jobId": "44905",
  "recordId": "avature-44905",
  "actorName": "avature-jobs-search-scraper",
  "actorVersion": "2.3.0",
  "title": "Portfolio (PORT) Enterprise Sales Executive - Financial Solutions",
  "company": "Bloomberg",
  "location": "San Francisco",
  "locations": ["San Francisco"],
  "locationDetails": { "name": "San Francisco", "remote": false, "hybrid": false },
  "businessArea": "Sales and Client Service",
  "department": "Sales and Client Service",
  "referenceNumber": "10054172",
  "description": "Our Team Bloomberg’s PORT Enterprise Solution is a comprehensive suite of portfolio management tools that delivers consistent, consolidated results across our client’s entire firm. Bloomberg’s Portfolio & Risk Analytics (PORT) solution unifies positions, risk and performance in one place...",
  "descriptionHtml": "<div>...</div>",
  "descriptionSections": [
    {
      "key": "responsibilities",
      "heading": "We will trust you to",
      "items": ["Utilize your strong product knowledge, technical skills, and market knowledge to generate revenue for Enterprise Businesses and all of Bloomberg’s buy-side solutions", "Partner with multiple stakeholders to run the enterprise sales engagements and long-term requirements"]
    },
    {
      "key": "qualifications",
      "heading": "You'll need to have",
      "items": ["Minimum of 3-5 years recent experience of selling portfolio analytics solutions, either with a vendor or as a market practitioner", "Proven consultative sales skills, including competitive market research, lead generation, prospecting, business development and closing sales"]
    }
  ],
  "responsibilities": ["Utilize your strong product knowledge, technical skills, and market knowledge to generate revenue for Enterprise Businesses and all of Bloomberg’s buy-side solutions"],
  "qualificationItems": ["Minimum of 3-5 years recent experience of selling portfolio analytics solutions, either with a vendor or as a market practitioner"],
  "benefitsText": "We offer one of the most comprehensive and generous benefits plans available and offer a range of total rewards that may include merit increases, incentive compensation (exempt roles only), paid holidays, paid time off, medical, dental, vision, short and long term disability benefits, 401(k) +match, life insurance, and various wellness programs, among others.",
  "salary": {
    "text": "145,000 - 235,000 USD Annual + Benefits + Bonus",
    "currency": "USD",
    "period": "year",
    "min": 145000,
    "max": 235000,
    "source": "description"
  },
  "salaryText": "145,000 - 235,000 USD Annual + Benefits + Bonus",
  "applicationLinks": ["https://bloomberg.avature.net/careers/Login?jobId=44905"],
  "applicationProvider": "bloomberg.avature.net",
  "sourceLinks": [
    { "url": "https://bloomberg.avature.net/careers/JobDetail/Portfolio-PORT-Enterprise-Sales-Executive-Financial-Solutions/44905", "source": "canonical" }
  ],
  "jobUrl": "https://bloomberg.avature.net/careers/JobDetail/Portfolio-PORT-Enterprise-Sales-Executive-Financial-Solutions/44905",
  "canonicalUrl": "https://bloomberg.avature.net/careers/JobDetail/Portfolio-PORT-Enterprise-Sales-Executive-Financial-Solutions/44905",
  "sourceWebsite": "https://bloomberg.avature.net",
  "sourceDomain": "bloomberg.avature.net",
  "sourceMode": "public-avature-html-detail",
  "scrapedAt": "2026-09-27T08:00:47.118Z",
  "found": true,
  "descriptionSectionCount": 4,
  "descriptionItemCount": 17,
  "requirementCount": 10,
  "applicationLinkCount": 1,
  "hasDescriptionHtml": true,
  "hasDescriptionLists": true,
  "hasApplicationAction": true,
  "hasCompanyProfile": true,
  "hasSalary": true,
  "hasStructuredData": true,
  "dataAvailable": true
}
```

#### Run summary

`OUTPUT_SUMMARY` and the compatibility key `OUTPUT` contain the final status and counts:

```json
{
  "recordType": "run-summary",
  "actorName": "avature-jobs-search-scraper",
  "status": "SUCCEEDED",
  "resultStatus": "COMPLETE",
  "limitedResults": false,
  "itemCount": 1,
  "jobCount": 1,
  "recordsWritten": 1,
  "completeRecords": 1,
  "uniqueRecordIds": 1,
  "dataAvailable": true,
  "pagesFetched": 1,
  "candidatesSeen": 2,
  "diagnosticCount": 0,
  "successfulRequests": 1,
  "failedRequests": 0,
  "source": "Public Avature tenant HTML",
  "extractionMethod": "avature_html_dom_and_semantic_sections"
}
```

`DIAGNOSTICS` contains structured request or extraction failures with the source URL, final URL, job ID when known, and diagnostic code; diagnostics stay in the key-value store and are never dataset rows. `RUN_HEALTH` contains a compact final status snapshot. `REQUEST_RECEIPTS` records every request attempt, including explicit denials and transport failures. The Apify platform `status` is only `SUCCEEDED` or `FAILED`; `resultStatus` separately reports `COMPLETE`, `LIMITED`, `SKIPPED`, `DEFERRED`, `NO_DATA`, or `FAILED`. If one or more complete job records were stored before a later non-block failure, the Actor finishes as `SUCCEEDED` with `resultStatus: LIMITED` and `limitedResults: true`. A fatal zero-row failure is `FAILED`/`FAILED`. A handled source denial is `SUCCEEDED`/`SKIPPED`; a generic request limitation or parser miss is `SUCCEEDED`/`DEFERRED`. `NO_DATA` is reported only when every successfully searched listing page has an explicit source empty-results message; the summary retains each message with its source URL. None of these outcomes inserts dummy or diagnostic rows into the job dataset.

### Development and validation

From this Actor directory:

```bash
npm ci
npm test
npm run check
npm run validate:schema
apify validate-schema .actor/input_schema.json
$env:APIFY_LOCAL_STORAGE_DIR = "storage-validation-<new-unique-name>"
apify run --resurrect --input-file .actor/input-single.json
npm run validate:dataset -- "$env:APIFY_LOCAL_STORAGE_DIR/datasets/default"
```

Choose a new actor-relative storage directory and confirm that it does not exist before each validation run. Preserve any pre-existing `storage` or legacy `apify_storage` contents before using the Apify CLI. `npm run validate:dataset` validates every dataset item against the strict schema, enforces more than 20 populated meaningful fields, rejects duplicate IDs and URLs, validates the run summary and receipts, and reconciles row counts with `OUTPUT.json`.

### Tips and responsible use

- Start with `maxPages: 1`, `maxItems: 5`, `maxDetailRequests: 5`, and `maxRequests: 10` when testing a new public tenant URL.
- Keep `requestDelayMs` conservative and avoid unnecessary repeated runs against the same tenant.
- Set `includeDetails: false` only when listing-page fields are sufficient; the richest fields generally require public detail pages.
- Inspect `OUTPUT_SUMMARY`, `RUN_HEALTH`, and `DIAGNOSTICS` when a run returns fewer records than requested.
- Avature tenants differ. A missing salary, benefits section, media item, or application link means the public page did not expose that field; the Actor does not invent or infer it.
- This Actor is not affiliated with Avature or any employer. Use it only for lawful, ethical purposes and respect each site's terms, robots rules, rate limits, and applicable privacy laws.

The Actor extracts only information publicly available on the requested pages. Public job pages can still contain personal data, such as a recruiter's contact address. Do not repurpose public personal data without a legitimate reason, and obtain qualified legal advice when required.

### FAQ

#### Why did I receive fewer jobs than `maxItems`?

The tenant may expose fewer public listings, the listing page may have changed, pagination may be unavailable, the request budget may have been reached, or records may have failed the completeness checks. Check `OUTPUT_SUMMARY`, `RUN_HEALTH`, and `DIAGNOSTICS`.

#### Why are some rich fields empty?

Fields such as salary, benefits, media, and application URLs are optional on Avature pages. They are emitted when visible in the public HTML. Detail enrichment must also be enabled and within `maxDetailRequests`.

#### Does the Actor apply for jobs?

No. It only records public application links. It never submits an application or sends credentials.

#### What should I report with a bug?

Include the input JSON, run ID, `OUTPUT_SUMMARY`, relevant diagnostic code, and the affected public URL. Do not include private credentials or private account data.

# Changelog

This Actor's version history is a separate document: https://apify.com/jobsapi/avature-jobs-search-scraper/changelog.md

# Actor input Schema

## `mode` (type: `string`):

Choose bounded listing search or direct public job URL collection.

## `jobUrl` (type: `string`):

A public Avature JobDetail URL used by single mode.

## `jobUrls` (type: `array`):

Public Avature JobDetail URLs used by multiple mode.

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

Public Avature careers, SearchJobs, or JobDetail URLs. The crawler stays on each supplied host.

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

Maximum public list pages to fetch across all supplied tenants.

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

Maximum unique public job records to emit.

## `maxDetailRequests` (type: `integer`):

Maximum public JobDetail pages to fetch.

## `maxRequests` (type: `integer`):

Maximum total public HTTP requests for this run.

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

Fetch public JobDetail pages for richer fields such as location, business area, reference number, and description.

## `timeoutMs` (type: `integer`):

Maximum time allowed for each public tenant request.

## `requestDelayMs` (type: `integer`):

Polite delay before each public tenant request.

## `maxRetries` (type: `integer`):

Retries for transient public HTTP failures.

## Actor input object example

```json
{
  "mode": "startUrls",
  "startUrls": [
    {
      "url": "https://bloomberg.avature.net/careers"
    }
  ],
  "maxPages": 2,
  "maxItems": 10,
  "maxDetailRequests": 25,
  "maxRequests": 80,
  "includeDetails": true,
  "timeoutMs": 30000,
  "requestDelayMs": 250,
  "maxRetries": 2
}
```

# Actor output Schema

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

No description

## `runSummary` (type: `string`):

No description

## `runSummaryCopy` (type: `string`):

No description

## `diagnostics` (type: `string`):

No description

## `requestReceipts` (type: `string`):

No description

## `runHealth` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("jobsapi/avature-jobs-search-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("jobsapi/avature-jobs-search-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 '{}' |
apify call jobsapi/avature-jobs-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jobsapi/avature-jobs-search-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/tn3zpbDHr7tJ9wNSU/builds/JKWdGdVerHcbB5uXn/openapi.json
