# ASVA Jobs Scraper (`maximedupre/asva`) Actor

Read public ASVA vacancies from the jobs feed, archive, or one vacancy page. Get structured vacancy details, including titles, descriptions, employers, locations, salary, classifications, application data, posting dates, and source URLs when published.

- **URL**: https://apify.com/maximedupre/asva.md
- **Developed by:** [Maxime Dupré](https://apify.com/maximedupre) (community)
- **Categories:** Jobs, Business, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.90 / 1,000 job vacancies

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

### 🏛️ ASVA vacancies for hiring teams

Recruiters, hiring researchers, and visitor-attraction teams can read public ASVA vacancies from the jobs feed, jobs archive, or one vacancy page. Each saved row includes the vacancy title, full description, employer, location, salary details, job classifications, application details, posting date, and source URL when published. Use these rows to review current roles, compare published details, and build a structured hiring dataset.

- Pull current postings from the public feed with **[ASVA Jobs Feed](https://apify.com/maximedupre/asva/examples/asva-jobs-feed)**.
- Review the public archive as structured vacancy data with **[ASVA Jobs Archive](https://apify.com/maximedupre/asva/examples/asva-jobs-archive)**.
- Turn one public vacancy page into a structured row with **[ASVA Vacancy Scraper](https://apify.com/maximedupre/asva/examples/asva-vacancy-scraper)**.
- Build a vacancy list for hiring research with **[ASVA Job Vacancies](https://apify.com/maximedupre/asva/examples/asva-job-vacancies)**.
- Explore public ASVA jobs as a dataset with **[ASVA Jobs](https://apify.com/maximedupre/asva/examples/asva-jobs)**.

#### 📋 Structured ASVA vacancy rows

The Actor saves one structured dataset row for each public vacancy it returns. A row keeps the published title and full description, source URL, and posting date when available. It can also include the employer, location, salary wording, safely parsed salary amounts, job classifications, and the public application route.

#### ▶️ Read the right public source

Choose the ASVA jobs feed, jobs archive, or one individual vacancy page. The archive and vacancy page choices need a public ASVA URL. You can filter by maximum posting age and set a maximum number of vacancies. Leave the maximum vacancies field empty to return all available vacancies until the selected public source is exhausted. The source controls what is available, so the Actor does not promise a complete historical archive beyond the public source.

#### ⚙️ Input

**Input fields**

| Field | Type | What it does |
| --- | --- | --- |
| `findVacanciesFrom` | string | Chooses the public ASVA jobs feed, jobs archive, or one individual vacancy page. |
| `archiveUrl` | string | The public ASVA jobs archive URL. Use it only when `findVacanciesFrom` is `archive`. |
| `vacancyPageUrl` | string | The public ASVA vacancy page URL. Use it only when `findVacanciesFrom` is `vacancyPage`. |
| `maxPostingAgeDays` | integer | Keeps vacancies posted within this many days. Leave it empty to keep all vacancies returned by the selected public source. |
| `maxItems` | integer | Caps the number of vacancies saved. Leave it empty to return all available vacancies until the selected public source is exhausted. |

**Example input**

This is the smallest successful current-beta feed input.

```json
{
  "findVacanciesFrom": "feed"
}
```

#### 🧾 Output

The Actor returns a link to the run dataset. Each dataset row is one public ASVA vacancy. A field can be absent when the source does not publish that value.

**Dataset link**

| Field | Type | What it does |
| --- | --- | --- |
| `dataset` | string | Opens the run's vacancy dataset and its overview table. |

**Vacancy row**

| Field | Type | What it does |
| --- | --- | --- |
| `title` | string | Published vacancy title. |
| `description` | string | Full published vacancy description. |
| `employer` | string | Published employer name, when available. |
| `location` | string | Published work location, when available. |
| `compensation` | object | Published salary wording and parsed amount, when available. |
| `compensation.salaryText` | string | Original salary wording from the vacancy. |
| `compensation.normalized` | object | Parsed salary amount when it can be read safely. |
| `compensation.normalized.currency` | string | Three-letter currency code for the parsed amount. |
| `compensation.normalized.amountMin` | number | Lower parsed salary amount. |
| `compensation.normalized.amountMax` | number | Upper parsed salary amount. For one amount, it equals the minimum amount. |
| `classification` | object | Published role, employment, and contract details. At least one classification field is present when this object is returned. |
| `classification.role` | string | Role classification published by the source, when available. |
| `classification.employmentType` | string | Employment type published by the source, when available. |
| `classification.contractType` | string | Contract type published by the source, when available. |
| `application` | object | Public application route and mode, when available. |
| `application.route` | string | Public route for applying, such as a URL or email address, when available. |
| `application.mode` | string | How the source says to apply, when available. |
| `postedAt` | string | Source-published posting date and time in date-time format, when available. |
| `sourceUrl` | string | Public ASVA vacancy page for the row. |

**Example vacancy row**

This unshortened row comes from a successful current-beta feed run and keeps the source values as returned.

```json
{
  "title": "Social Media Content Creator",
  "description": "About Lost Shore Surf Resort Lost Shore is about bringing a world-first and world-beating surf resort to the outskirts of the capital. The largest inland wave pool in Europe, has arrived next to Europe’s largest indoor climbing arena, and is putting Scotland on the map for all the right reasons! But it’s the range of other activities and leisure offerings that make us so special, offering something for everyone. Picture a surfing paradise where surfers, tourists, and locals converge—a place where adventure meets relaxation About the role We’re looking for a hands-on, self-sufficient content creator to help bring the Lost Shore story to life across social media. This isn’t a support role sitting in the background — you’ll often be the one on the ground, camera in hand, capturing the resort, its guests, and its people in the moment. You’ll need to be comfortable working independently, moving fast, and making creative calls on the fly, while still collaborating closely with the Social Media Manager and wider marketing team on strategy and concepts. This role suits someone who’s equal parts creative and operator — happy to be handed a loose brief and a tight deadline and come back with something that looks great and sounds like Lost Shore. Comfortable both taking direction from the Social Media Manager and running solo when the moment calls for it (a guest walking past at the right time, a swell rolling in, a pro athlete with a 20-minute window). This role requires 24 hours per week (three days). We offer flexibility in how these hours are worked; however, due to the fast-paced nature of the resort and the need to capture content as opportunities arise, the successful candidate will need to be flexible in return. Weekend working will be required, particularly during busy periods and events. What you’ll do Content Capture • Film dynamic photo and video content around the resort for Instagram, TikTok, Facebook, LinkedIn, YouTube and other platforms • Shoot confidently on both mobile and modern mirrorless cameras, choosing the right tool for the scenario and desired output • Understand camera setups and techniques including vlog-style shooting • Capture basic photography for press use when needed (not a core requirement, but a strong plus) Editing & Production • Edit and produce high-quality video and static content using DaVinci Resolve and the Edits app, knowing when each is the right tool for the job • Turn raw footage into short-form content that is engaging, on-brand, and accurate to the story being told Storytelling & Concept Development • Take a story from concept through to finished output, with a clear sense of how to tell it effectively in short-form formats • Collaborate with the Social Media Manager and marketing team to develop creative concepts and campaign ideas aligned with brand voice and content pillars • Bring fresh, fun, and original ideas to strengthen Lost Shore’s visual and digital presence People & Interviews • Engage and interview surfers, guests, and occasionally celebrities or professional athletes — often with very little prep time • Put subjects at ease quickly and build genuine rapport before filming; this is a core strength of Lost Shore’s content and a key expectation of this role Planning & Operations • Plan and manage content scheduling via Meta platforms or third-party scheduling tools • Organise creative assets so they’re easily accessible to the marketing team • Collaborate with internal teams to understand content needs across the business • Support with DM and comment monitoring and replies Qualifications Essential • Solid understanding of social media best practices, with a working knowledge of metrics and platform algorithms • Confident filming on both mobile and mirrorless cameras, understanding the strengths of each • Proficient in DaVinci Resolve and the Edits app • Strong short-form storytelling instincts — can conceive, shoot, and edit a piece start to finish quickly • Comfortable planning/scheduling content via Meta Business Suite or similar tools • Naturally personable — able to interview and direct people (including high-profile guests) at short notice while putting them at ease • Able to work independently, often in a fast-paced, changeable environment (weather, tides, guest schedules) Desirable • Basic photography skills for press/media use • Prior experience working within a hospitality, resort, or action-sports brand • An understanding of surfing and surf culture **Please note – Applications will be reviewed as they are received, and we may invite candidates to interview before the closing date. We encourage you to apply as soon as possible.**",
  "sourceUrl": "https://www.asva.co.uk/jobs/social-media-content-creator-2/",
  "postedAt": "2026-09-17T16:01:21.000Z",
  "employer": "Lost Shore Surf Resort",
  "location": "Lost Shore Surf Resort, Edinburgh",
  "compensation": {
    "salaryText": "£16,800 per year",
    "normalized": {
      "currency": "GBP",
      "amountMin": 16800,
      "amountMax": 16800
    }
  },
  "classification": {
    "role": "Marketing & PR",
    "employmentType": "Part Time"
  },
  "application": {
    "route": "https://ats.rippling.com/en-GB/lostshorecareers/jobs/2d6c6e41-e9a9-41ba-a6c1-549dc0df1663",
    "mode": "View On Website"
  }
}
```

#### 💳 Pricing

This Actor uses pay-per-event pricing. The `Job vacancy` event is charged for each public ASVA job vacancy saved to the dataset. The number of charged events follows the number of saved vacancies, and the current per-event price is shown in the pricing panel.

#### 🔌 Integrations

Open the dataset through the Apify API or built-in export formats. Use the dataset link in your own hiring research or reporting workflow.

https://www.youtube.com/watch?v=bNACk1\_S\_6w\&list=PLObrtcm1Kw6MUrlLNDbK9QRg8VDJg0gOW\&index=4

#### ❓ FAQ

##### Can I read one public vacancy page?

Yes. Set `findVacanciesFrom` to `vacancyPage` and enter one public ASVA vacancy page URL.

##### Can I use the ASVA jobs archive?

Yes. Set `findVacanciesFrom` to `archive` and enter one public ASVA jobs archive URL.

##### What happens when a vacancy does not publish salary or employer details?

Those optional fields can be absent from that row. The Actor keeps the published vacancy title, description, and source URL required by the dataset when they are available.

##### How can I keep only recent vacancies?

Set `maxPostingAgeDays` to the number of days you want. Leave it empty to keep all vacancies returned by the selected public source.

##### What does an empty maximum vacancies value do?

It returns all available vacancies until the selected public source is exhausted. Set `maxItems` when you want a bounded run.

##### Does the Actor read private vacancies or applicant data?

No. It reads public ASVA sources only and does not include private or applicant-only data.

##### Is this a complete historical jobs archive?

No. The public source controls the vacancies available to the run. Use the archive or a direct vacancy page when you need a specific public source page.

### 📝 Changelog

**v0.0** (20-09-2026)

- Initial release.

### 🆘 Support

For issues, questions, or feature requests, [file a ticket](https://console.apify.com/actors/maximedupre~asva/issues) and I'll fix or implement it in less than 24h 🫡

### 🔗 Related Actors

- [Goodmoves Jobs Scraper](https://apify.com/maximedupre/goodmoves-jobs-scraper) for Scottish charity vacancies with employer, salary, and application data.
- [Doing Good Leeds Scraper](https://apify.com/maximedupre/doing-good-leeds-scraper) for public Leeds charity jobs and related community opportunities.
- [Handshake Jobs Scraper](https://apify.com/maximedupre/handshake-jobs-scraper) for public jobs found by keyword, location, or direct URL.
- [CWjobs Scraper](https://apify.com/maximedupre/cwjobs-scraper) for UK technology vacancies with employer, salary, and location fields.
- [Jobsite Scraper](https://apify.com/maximedupre/jobsite-scraper) for public UK job listings found by role, location, or URL.

**Made with ❤️ by Maxime Dupré**

# Actor input Schema

## `findVacanciesFrom` (type: `string`):

Choose the public ASVA source to search. The jobs feed returns its current public feed items.

## `archiveUrl` (type: `string`):

Enter one public URL for the ASVA jobs archive. Use this only for the ASVA jobs archive choice.

## `vacancyPageUrl` (type: `string`):

Enter one public URL for an ASVA vacancy page. Use this only for the Individual vacancy page choice.

## `maxPostingAgeDays` (type: `integer`):

Keep vacancies posted within this many days. Omit it to keep all vacancies returned by the selected public source.

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

Stop after this many vacancies. Leave it empty to return all available vacancies until the selected public source is exhausted.

## Actor input object example

```json
{
  "findVacanciesFrom": "feed",
  "maxPostingAgeDays": 30
}
```

# Actor output Schema

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

Open structured ASVA vacancy results from the selected public source.

# 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 = {
    "findVacanciesFrom": "feed",
    "maxPostingAgeDays": 30
};

// Run the Actor and wait for it to finish
const run = await client.actor("maximedupre/asva").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 = {
    "findVacanciesFrom": "feed",
    "maxPostingAgeDays": 30,
}

# Run the Actor and wait for it to finish
run = client.actor("maximedupre/asva").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 '{
  "findVacanciesFrom": "feed",
  "maxPostingAgeDays": 30
}' |
apify call maximedupre/asva --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,maximedupre/asva"
        }
    }
}
```

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/eLV4HWfCHjzkwnfmR/builds/QmnCeA5dVnpw9GFMb/openapi.json
