# VK Posts Scraper (`khadinakbar/vk-posts-scraper`) Actor

Scrape public VK wall posts and token-backed keyword search. Use for social monitoring, CIS research, and OSINT. Not for VK profiles, videos, member lists, or private content. Returns one record per post with text, author, engagement, media, URL. $0.005/post + $0.00005 start.

- **URL**: https://apify.com/khadinakbar/vk-posts-scraper.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** Social media, Automation, MCP servers
- **Stats:** 5 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 1,000 post scrapeds

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?

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

## VK Posts Scraper

VK Posts Scraper collects public VK wall posts and token-backed keyword search results into one dataset record per post. It accepts VK handles, community or profile URLs, owner IDs, wall post URLs, or a keyword search string with a VK access token. Each record includes post text, author details, engagement counts, media attachments, and the canonical post URL. The actor is usable through Apify MCP for structured VK post retrieval in automation workflows.

### Best fit and connected workflows

Use this actor when your workflow starts with a public VK wall, a specific post URL, or a token-backed keyword search across public posts, and you want structured rows for downstream analysis.

It fits well when you need to:

- monitor public VK communities or public figures for new wall activity
- collect engagement signals such as likes, reposts, comments, and views
- extract post-level evidence for research, OSINT, or compliance review
- send VK post rows into spreadsheets, databases, BI tools, or LLM pipelines

#### Focused standalone workflow

This Actor is designed as a focused standalone workflow.

### Practical scenario

A research analyst starts with the public handle `durov` and wants a compact export of recent wall posts. The analyst sets a post cap and runs the actor. The dataset returns fields such as `postUrl`, `authorName`, `text`, `date`, `likes`, `reposts`, `comments`, `views`, and `source`. From those fields, the analyst can decide which posts deserve deeper review, then open the canonical VK links or pass the rows into a reporting pipeline.

### Input fields

| Field | Type | Purpose |
|---|---|---|
| `targets` | array | VK walls or posts to scrape. Accepts handles, URLs, owner IDs, or wall post URLs. Defaults to `durov`. |
| `searchQuery` | string | Token-backed keyword search across public VK posts. Use together with `vkAccessToken`. |
| `maxPosts` | integer | Total cap across all targets and search. Clamped to 1-1000. |
| `maxPostsPerTarget` | integer | Per-target cap before moving to the next target. Clamped to 1-500 and bounded by `maxPosts`. |
| `vkAccessToken` | string | Optional VK access token for the API-backed path and keyword search. |
| `proxyCountry` | string | Residential proxy country code used for outbound requests. Default is `RU`. |
| `saveHtmlSnapshot` | boolean | Saves rendered VK wall HTML to key-value storage for selector troubleshooting. |
| `proxyConfiguration` | object | Advanced Apify proxy override. Default uses Apify Residential in the selected country. |

#### Focused input example

```json
{
  "targets": ["durov", "https://vk.com/team"],
  "maxPosts": 25,
  "proxyCountry": "RU",
  "saveHtmlSnapshot": false
}
```

#### Keyword search example

```json
{
  "searchQuery": "machine learning",
  "vkAccessToken": "<your VK service token>",
  "maxPosts": 100
}
```

### Output fields

The actor writes one validated dataset item per VK post. Each item follows the schema below.

| Field | Type | Meaning |
|---|---|---|
| `postId` | integer | Numeric VK wall post identifier within the owner wall. |
| `ownerId` | integer | VK wall owner ID. Negative values identify communities; positive values identify users. |
| `postUrl` | string | Canonical desktop VK URL for the post. |
| `type` | string | Record type inferred from VK data, usually `post` or `repost`. |
| `isPinned` | boolean | Whether VK marks the post as pinned to the wall. |
| `text` | string | Visible post body text. |
| `date` | string or null | ISO 8601 timestamp when available. |
| `timestamp` | integer or null | Unix seconds when VK exposes them. |
| `authorId` | integer or null | Numeric VK author ID. |
| `authorName` | string or null | Display name of the author. |
| `authorScreenName` | string or null | VK screen name when available. |
| `authorUrl` | string or null | Canonical VK author URL when available. |
| `authorType` | string or null | Author type, such as user or community, when inferred. |
| `likes` | integer | Likes shown for the post. |
| `reposts` | integer | Reposts shown for the post. |
| `comments` | integer or null | Comment count when exposed. |
| `views` | integer or null | View count when exposed. |
| `attachments` | array | Visible media and link attachments. |
| `repostOf` | object or null | Original post metadata when the record is a repost. |
| `signerId` | integer or null | VK signer ID for community posts when exposed. |
| `source` | string | Input target or search query that produced the row. |

#### Illustrative dataset record

```json
{
  "postId": 456239017,
  "ownerId": 1,
  "postUrl": "https://vk.com/wall1_456239017",
  "type": "post",
  "isPinned": false,
  "text": "Hello world",
  "date": "2024-01-15T09:30:00.000Z",
  "timestamp": 1705311000,
  "authorId": 1,
  "authorName": "Pavel Durov",
  "authorScreenName": "durov",
  "authorUrl": "https://vk.com/durov",
  "authorType": "user",
  "likes": 48213,
  "reposts": 1207,
  "comments": 9032,
  "views": 2841992,
  "attachments": [
    {
      "type": "photo",
      "url": "https://sun9-1.userapi.com/example.jpg",
      "title": null
    }
  ],
  "repostOf": null,
  "signerId": null,
  "source": "durov"
}
```

### How it works

The actor uses a JS Playwright Camoufox template and writes validated dataset rows plus key-value store records for execution summary data.

Implementation facts from the live contract:

- the default route uses Apify Residential proxy in the selected country
- tokenless scraping is available for public walls
- VK access token mode is available for API-backed collection and keyword search
- the actor writes `OUTPUT` and `RUN_SUMMARY` records in key-value storage
- the run summary includes route, validation, billing, and skipped-target diagnostics
- one validated dataset record corresponds to one returned VK post

### Evergreen pricing

This actor uses Pay per event pricing plus Apify platform usage.

- The primary billable event is `Post scraped`.
- There is also a charged actor-start event.
- Apify compute and proxy usage are billed separately through your Apify platform settings.
- For current pricing details, open the live Pricing tab in Apify.

Example in words: if a run returns fifty posts, the execution includes fifty post-scraped events plus one actor-start event, and Apify platform usage is billed separately.

### Use with AI agents (MCP)

This actor is available as an Apify Actor usable through Apify MCP. It is a tool for retrieving structured VK post records from a defined input set.

**Exact Actor identity:** `khadinakbar/vk-posts-scraper`

Tool description: submit structured inputs such as `targets`, `searchQuery`, and `maxPosts`, then read back normalized post records from the dataset.

> Collect the latest public posts from `durov` and return each record with post URL, author, date, engagement counts, attachments, and source. Use the result set for a weekly monitoring brief.

Output interpretation:

- Use `postUrl` as the canonical post link.
- Use `source` to trace which target or search query produced the row.
- Use `repostOf` to distinguish original posts from reposted content.
- Use `comments` and `views` as nullable fields when VK exposes them.
- For pagination and scope, `maxPosts` is the total run cap and `maxPostsPerTarget` limits how many posts are taken from each target.
- For cost guidance, each returned post is one billable `post-scraped` event.

### Apify API example

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({
  token: process.env.APIFY_TOKEN,
});

const run = await client.actor('khadinakbar/vk-posts-scraper').call({
  targets: ['durov'],
  maxPosts: 10,
  proxyCountry: 'RU',
});

const datasetId = run.defaultDatasetId;
const { items } = await client.dataset(datasetId).listItems();

console.log(items);
```

### Best results and outcome guidance

Use a clear target list or a single search query, then set `maxPosts` to the number of rows you want to review. If you need wall coverage, pass handles, URLs, owner IDs, or wall post URLs in `targets`. If you need token-backed keyword search across public VK posts, provide `searchQuery` together with `vkAccessToken`.

`maxPostsPerTarget` is useful when you want to distribute a larger run across several communities. `saveHtmlSnapshot` is available when you want rendered HTML stored for troubleshooting selectors. The `proxyCountry` field controls the outbound proxy region.

### Design note

I found that the live dataset contract includes `source` on every row, which makes it straightforward to trace each post back to the input target or keyword query that produced it.

### FAQ

#### Can I send wall handles, URLs, and owner IDs together?

Yes. The `targets` field accepts a mixed list of handles, URLs, owner IDs, and wall post URLs.

#### When should I use `searchQuery`?

Use `searchQuery` when you want token-backed keyword search across public VK posts. Pair it with `vkAccessToken`.

#### What is returned for each post?

Each dataset item includes the post URL, identifiers, text, author details, engagement counts, attachments, repost metadata, and the input source.

#### Can this actor process a single post URL?

Yes. Single-post URLs are accepted in `targets`, and token-backed API collection is also available.

#### Where can I review execution diagnostics?

Check the `OUTPUT` and `RUN_SUMMARY` records in key-value storage after the execution finishes.

### Responsible use

Use this actor only for public VK data that you are entitled to collect and process. Review VK terms, applicable laws, and your own compliance requirements before running large or repeated jobs. When using the output, respect privacy, data-protection, and security obligations that apply to your use case.

# Actor input Schema

## `targets` (type: `array`):

VK walls or posts to scrape. Accepts handles, URLs, owner IDs, or wall post URLs such as 'durov', 'https://vk.com/team', '-22822305', or 'https://vk.com/wall-1/_123456'. Defaults to \['durov'] when no input is supplied. NOT a keyword search field; use searchQuery for token-backed keyword search.

## `searchQuery` (type: `string`):

Free-text keyword to search across public VK posts. Example: 'machine learning'. Defaults to blank and is ignored unless vkAccessToken is supplied, because VK newsfeed search is token-only. NOT a VK wall URL or handle.

## `maxPosts` (type: `integer`):

Hard cap on total posts returned across all targets and search. Example: 50 returns at most 50 billable post rows. Defaults to 100 and the runtime clamps the value to 1-1000. NOT a page count; one returned VK post equals one billable event.

## `maxPostsPerTarget` (type: `integer`):

Cap on posts taken from each individual VK wall before moving to the next target. Example: 25 spreads a 100-post budget over several communities. Defaults to 50 and is clamped to maxPosts and 500. NOT a global run cap; use maxPosts for that.

## `vkAccessToken` (type: `string`):

Optional VK API service or user access token. Example: a service token created in the VK app dashboard at dev.vk.com. Defaults to blank, which uses tokenless public-wall scraping and disables keyword search. NOT your VK password, login cookie, or private account session.

## `proxyCountry` (type: `string`):

Residential proxy country code used to reach VK. Example: 'RU'. Defaults to RU because VK commonly throttles datacenter and non-CIS IPs. NOT a content-language filter; it only controls the outbound proxy region.

## `saveHtmlSnapshot` (type: `boolean`):

Saves rendered VK wall HTML to the key-value store for selector troubleshooting. Example: true writes DEBUG\_DOM\_<slug> records. Defaults to false for normal runs. NOT needed for API-token runs or routine scraping.

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

Advanced Apify proxy override. Example: keep the default Residential proxy unless you know your target needs another group. Defaults to Apify Residential in proxyCountry. NOT required for normal runs; changing this can reduce VK reliability.

## Actor input object example

```json
{
  "targets": [
    "durov",
    "https://vk.com/team",
    "-22822305"
  ],
  "searchQuery": "machine learning",
  "maxPosts": 1,
  "maxPostsPerTarget": 1,
  "proxyCountry": "RU",
  "saveHtmlSnapshot": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `posts` (type: `string`):

Dataset items. One validated record per VK post returned.

## `output` (type: `string`):

Compact terminal outcome and counts for automation clients.

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

Detailed route, validation, billing, and skipped-target diagnostics.

# 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 = {
    "targets": [
        "durov"
    ],
    "maxPosts": 1,
    "maxPostsPerTarget": 1
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/vk-posts-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 = {
    "targets": ["durov"],
    "maxPosts": 1,
    "maxPostsPerTarget": 1,
}

# Run the Actor and wait for it to finish
run = client.actor("khadinakbar/vk-posts-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 '{
  "targets": [
    "durov"
  ],
  "maxPosts": 1,
  "maxPostsPerTarget": 1
}' |
apify call khadinakbar/vk-posts-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,khadinakbar/vk-posts-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/4jzkH9W2c9eHPF660/builds/VRrk9DRtraVAPVwJz/openapi.json
