# Barnsley CVS Jobs Scraper (`memo23/barnsleycvs-scraper`) Actor

Scrape the barnsleycvs.org.uk Webflow job board for Barnsley voluntary-sector vacancies. Title, employer, parsed salary, closing date from the listing; full HTML description per job via optional detail enrichment. ~5-10 live vacancies. JSON or CSV out.

- **URL**: https://apify.com/memo23/barnsleycvs-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Jobs, AI, Agents
- **Stats:** 2 total users, 1 monthly users, 96.7% 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.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#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

## Barnsley CVS Jobs Scraper

**Scrape the barnsleycvs.org.uk Webflow-hosted job board.** The `/jobs` listing renders every vacancy server-side with title, employer, salary (parsed), and closing date. Optional detail enrichment fetches each `/job-positions/<slug>` page for the full HTML description. JSON or CSV out, no compute charge per run, just per result.

#### How it works

![How Barnsley CVS Scraper works](https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/how-it-works-barnsleycvs.png)

#### ✨ Why use this scraper?

Barnsley CVS hosts the town's voluntary-sector jobs board for member charities — children's services, fundraising, project work, finance, community engagement. Tracking Barnsley nonprofit hiring? Building a regional South Yorkshire dashboard? Looking for partner orgs by employer?

- 🎯 **Two starting points.** The `/jobs` listing URL (default) or any direct `/job-positions/<slug>` URL (filters the listing).
- ⚡ **Single HTTP call for the listing.** Webflow renders every CMS Collection item server-side — title, employer, salary, closing date all inline.
- 📋 **Detail-page enrichment.** Optional one-fetch-per-job to extract the full HTML description from `/job-positions/<slug>`.
- 💰 **Salary parsed.** "£26,403 - £28,142 per annum" → structured `{currency, min, max, raw}`.
- 📅 **Closing date inline.** Card's "Deadline: …" line captured.
- 🏙️ **Barnsley focus.** Member charities — GROW, Roundabout Ltd, Barnsley CVS itself, Rotherham Federation of Communities Ltd, and more.
- 📤 **Clean exports.** One row per vacancy with optional full HTML description. JSON + CSV exported automatically.

#### 🎯 Use cases

| Team | What they build |
|------|-----------------|
| **Barnsley CVS members** | Cross-charity recruitment intelligence in their own borough |
| **South Yorkshire CVS network** | Aggregate with VA Rotherham + Sheffield for regional dashboards |
| **Funders** | Salary intelligence across small Barnsley charities |
| **Sector recruiters** | Daily new-vacancy feeds |
| **Volunteer co-ordinators** | Track partner orgs hiring for paid roles |

#### 📥 Supported inputs

| URL pattern | Behaviour |
|---|---|
| `https://barnsleycvs.org.uk/jobs` | **Full listing** (default) |
| `https://barnsleycvs.org.uk/job-positions/<slug>` | **Single job** — fetches the listing and filters to that slug |

Leave `startUrls` empty for the full listing.

**Not supported:** hosts outside `barnsleycvs.org.uk`.

#### 🔄 How it works

1. **Fetch the `/jobs` listing once** (Webflow SSR HTML).
2. **Find every `.collection-item-job-position` block** using cheerio.
3. **For each card**, extract:
   - `.job-position-name` → title + slug
   - Three `.info-job-wrappr` blocks in order: employer, deadline, salary
4. **For each card (when `enrichDetail: true`)**, fetch `/job-positions/<slug>` for the full HTML description.
5. **Push one normalised row per vacancy** to the dataset.

#### ⚙️ Input parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| `startUrls` | array | `["https://barnsleycvs.org.uk/jobs"]` | Listing URL or single-job URLs (slug filter). |
| `enrichDetail` | boolean | `true` | When `true`, fetches each `/job-positions/<slug>` page for the full HTML description. Disable to skip — listing alone gives title, employer, salary, closing date. |
| `maxItems` | integer | `1000` | Hard cap on rows pushed (typically 5-10 live). |
| `maxConcurrency` | integer | `3` | Parallel detail-page fetch limit. |
| `maxRequestRetries` | integer | `5` | Retries before a failed request is given up. |
| `proxy` | object | No proxy | Webflow CDN does not anti-bot. |

#### 📊 Output overview

Each scraped vacancy is one **single dataset row** of `type: "job"`. Listing fields merged with optional detail-page HTML description.

#### 📦 Output sample

```json
{
  "type": "job",
  "source": "barnsleycvs.org.uk",
  "jobId": "project-worker",
  "slug": "project-worker",
  "jobUrl": "https://barnsleycvs.org.uk/job-positions/project-worker",
  "title": "Project Worker",
  "description": "<div>Project Worker role at GROW supporting young people in Barnsley…</div>",
  "descriptionText": "Project Worker role at GROW supporting young people in Barnsley…",
  "companyName": "GROW",
  "companyWebsite": null,
  "companyDomain": null,
  "location": "Barnsley, South Yorkshire",
  "remote": false,
  "salary": {
    "currency": "GBP",
    "min": 26403,
    "max": 28142,
    "raw": "£26,403 - £28,142 per annum"
  },
  "salaryRaw": "£26,403 - £28,142 per annum",
  "categories": [],
  "employmentTypes": [],
  "contractType": null,
  "status": "publish",
  "postedDate": null,
  "closingDate": "10 am 18th May 2026",
  "modifiedDate": null,
  "applyType": "internal",
  "applyUrl": "https://barnsleycvs.org.uk/job-positions/project-worker",
  "applyEmail": null,
  "externalApplyUrl": null,
  "scrapedAt": "2026-05-20T00:13:00.000Z"
}
```

#### 🗂 Key output fields

| Group | Fields |
|---|---|
| **Identifiers** | `type`, `source`, `jobId`, `slug`, `jobUrl`, `scrapedAt` |
| **Content** | `title` (from `.job-position-name`), `description` (HTML, from detail page when `enrichDetail: true`), `descriptionText` (plain) |
| **Dates** | `closingDate` (from card "Deadline:" field) |
| **Employer** | `companyName` (from first `.info-job-wrappr`) |
| **Location** | `location` (always Barnsley, South Yorkshire) |
| **Compensation** | `salary.{currency, min, max, raw}`, `salaryRaw` |
| **Apply flow** | `applyType`, `applyUrl` (the BCVS page) |

#### ❓ FAQ

**Why is `applyType` always "internal"?**
Barnsley CVS cards don't surface an `mailto:` or outbound URL — the "Learn more" button goes to their own `/job-positions/<slug>` page where the applicant follows the charity's own instructions. The actor preserves the BCVS URL in `applyUrl`.

**Why are some closing dates verbose ("10 am 18th May 2026")?**
The deadline value comes verbatim from the Webflow CMS — charities format it freely. We don't normalise to ISO because the format varies.

**Why is `location` always "Barnsley, South Yorkshire"?**
Barnsley CVS doesn't tag location per job — every member is in the borough. Set as a constant for downstream geocoding consistency.

**Can I scrape private pages or applicant data?**
No. Only the public `/jobs` listing and public `/job-positions/<slug>` pages.

**How do I limit results?**
Set `maxItems`. With only 5-10 live vacancies, `maxItems: 100` covers everything.

#### 💬 Support

- For issues or feature requests, please use the **Issues** tab on the actor's Apify Console page.
- Author's website: <https://muhamed-didovic.github.io/>
- Email: <muhamed.didovic@gmail.com>

#### 🛠 Additional services

- Custom output shape, additional fields, or one-off datasets: <muhamed.didovic@gmail.com>
- Similar scrapers for other CVS / volunteer hubs (VA Rotherham, Doing Good Leeds, VAS Sheffield, York CVS): drop an email.
- For API access (no Apify fee, just usage): <muhamed.didovic@gmail.com>

#### 🔎 Explore more scrapers

See other scrapers at [memo23's Apify profile](https://apify.com/memo23) — covering job boards, real estate, social media, and more.

***

### 🤖 For AI Agents & LLM Apps

Compact reference for AI agents calling this actor via the [Apify MCP server](https://mcp.apify.com) or the Apify API (actor: `memo23/barnsleycvs-scraper`).

**Purpose:** Scrape the Barnsley CVS Webflow jobs board (barnsleycvs.org.uk) — one row per vacancy with title, employer, parsed salary, closing date, and optional full HTML description.

**Minimal input:**

```json
{
  "startUrls": ["https://barnsleycvs.org.uk/jobs"],
  "enrichDetail": true,
  "maxItems": 50,
  "maxConcurrency": 3,
  "minConcurrency": 1,
  "maxRequestRetries": 5,
  "proxy": {}
}
```

**Output:** one dataset row per vacancy — `type`, `source`, `jobId`, `slug`, `jobUrl`, `title`, `description`, `descriptionText`, `companyName`, `companyWebsite`, `companyDomain`, `location`, `remote`, `salary {currency, min, max, raw}`, `salaryRaw`, `categories`, `employmentTypes`, `contractType`, `status`, `postedDate`, `closingDate`, `modifiedDate`, `applyType`, `applyUrl`, `applyEmail`, `externalApplyUrl`, `scrapedAt`.

**Behaviors an agent should know:**

- `startUrls` accepts the `/jobs` listing (default) or `/job-positions/<slug>` single-job URLs (slug filters the listing). Empty = full listing.
- Always set `maxItems`. Barnsley CVS lists only ~5-10 live vacancies, so an uncapped run stays small.
- `enrichDetail: true` (default) adds one detail fetch per job for the full HTML description; set `false` and the listing alone still gives title, employer, salary, and closing date.
- `closingDate` is verbatim Webflow CMS text (e.g. "10 am 18th May 2026"), not normalised to ISO. `location` is always "Barnsley, South Yorkshire". Public pages only, no authenticated endpoints.
- Billed per result — no per-run compute charge.

***

### ⚠️ Disclaimer

This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by Barnsley CVS, barnsleycvs.org.uk, Webflow Inc., or any of their subsidiaries or affiliates. All trademarks mentioned are the property of their respective owners.

The scraper accesses only the publicly available `/jobs` listing page and public `/job-positions/<slug>` pages on barnsleycvs.org.uk — no authenticated endpoints, recruiter-only features, or content behind a login. Users are responsible for ensuring their use complies with barnsleycvs.org.uk's Terms of Service, applicable data-protection law (GDPR, CCPA, etc.), and any contractual obligations of their own organisation.

***

### SEO Keywords

barnsley cvs scraper, scrape barnsleycvs.org.uk, barnsley cvs jobs api, barnsley voluntary sector jobs scraper, barnsley charity jobs scraper, south yorkshire charity recruitment data, Apify barnsley cvs, barnsley nonprofit jobs api, barnsley third sector jobs scraper, barnsley community sector jobs, webflow cms scraper, webflow collection scraper, charityjob alternative scraper, va rotherham alternative scraper, vassheffield alternative scraper, doing good leeds alternative scraper, uk cvs jobs scraper, south yorkshire voluntary sector recruitment data, barnsley hiring trends data

# Actor input Schema

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

Supported shapes: `https://barnsleycvs.org.uk/jobs`, `https://barnsleycvs.org.uk/job-positions/<slug>`. Leave empty for the full listing.

## `enrichDetail` (type: `boolean`):

When enabled, each job triggers one extra HTTP call to /job-positions/<slug> to extract the long-form HTML description. Disable to skip — the listing already gives you title, employer, salary, and closing date.

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

Hard cap on rows pushed. Barnsley CVS typically lists 5-10 live vacancies.

## `maxConcurrency` (type: `integer`):

Maximum detail-page fetches in parallel.

## `minConcurrency` (type: `integer`):

Reserved.

## `maxRequestRetries` (type: `integer`):

Retries before a failed request is given up.

## `proxy` (type: `object`):

Leave empty — the actor already routes all traffic through its own built-in residential proxy at no extra cost to you. Only set this if you want to use your own proxies.

## Actor input object example

```json
{
  "startUrls": [
    "https://barnsleycvs.org.uk/jobs"
  ],
  "enrichDetail": true,
  "maxItems": 1000,
  "maxConcurrency": 3,
  "minConcurrency": 1,
  "maxRequestRetries": 5
}
```

# 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 = {
    "startUrls": [
        "https://barnsleycvs.org.uk/jobs"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/barnsleycvs-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 = { "startUrls": ["https://barnsleycvs.org.uk/jobs"] }

# Run the Actor and wait for it to finish
run = client.actor("memo23/barnsleycvs-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 '{
  "startUrls": [
    "https://barnsleycvs.org.uk/jobs"
  ]
}' |
apify call memo23/barnsleycvs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,memo23/barnsleycvs-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/9pQsFRcwf6S03XpgE/builds/m75TVhMMDLvyhSguX/openapi.json
