# VK Posts Scraper (`molded_mountainpass/my-actor-2`) Actor

Extract wall posts from public VK (VKontakte) profiles and communities: post text, exact UTC timestamps, attachment URLs with VK object IDs, media types and repost flags. Add a VK access token to also get engagement counts, authors and comment threads. Export to JSON, CSV or Excel.

- **URL**: https://apify.com/molded\_mountainpass/my-actor-2.md
- **Developed by:** [Divya Raj](https://apify.com/molded_mountainpass) (community)
- **Categories:** Social media, News, Videos
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.11 / actor start

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/platform/actors/running/actors-in-store#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

Extracts wall posts from public VK profiles and communities, with every field VK exposes for a post: text, author, engagement stats, attachment URLs, repost chains, geotags, poll results and — optionally — full comment threads.

### Input

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `vkTargets` | string\[] | **required** | Handles (`durov`), profile/community URLs (`https://vk.com/kinopoisk`), signed owner IDs (`-40316705`), or direct post links (`https://vk.com/wall1_45678`). |
| `accessToken` | string (secret) | — | VK API token with the `wall` scope. Strongly recommended — see [Extraction modes](#extraction-modes). |
| `maxItems` | integer | `500` | Hard cap on posts stored across all targets. |
| `postsPerTarget` | integer | — | Optional per-target cap. |
| `publishedAfter` | string | — | `YYYY-MM-DD` or ISO-8601. Pagination stops once older posts are reached. |
| `publishedBefore` | string | — | `YYYY-MM-DD` or ISO-8601. A bare date includes the whole day. |
| `postFilter` | `all` | `owner` | `others` | `all` | Which posts to read from the wall (API mode only). |
| `includeComments` | boolean | `false` | Fetch comment threads, including replies. API mode only. |
| `maxComments` | integer | `100` | Comments fetched per post. |
| `includeRawPost` | boolean | `false` | Attach the unmodified VK payload as `rawPost`. |
| `proxyConfiguration` | object | Residential | VK blocks most datacenter IP ranges. |

```json
{
    "vkTargets": ["kinopoisk", "https://vk.com/durov"],
    "accessToken": "vk1.a.…",
    "maxItems": 200,
    "publishedAfter": "2024-01-01",
    "includeComments": true
}
```

### Extraction modes

**API mode** (an `accessToken` is supplied) calls the official VK API — `wall.get`, `wall.getById`, `wall.getComments`. This is the mode the Actor is built around and the only one that returns complete data. Get a token by creating a [standalone VK application](https://dev.vk.com/) and issuing a user token with the `wall` scope.

**HTML mode** (no token) scrapes `m.vk.com` in a browser. It is a genuine fallback, not a substitute: VK's public HTML has no attachment URLs beyond thumbnails, often no view counts, and dates that frequently cannot be resolved to an exact timestamp (those posts get `postedAt: null` and a raw `postedAtLabel` instead). Closed walls and single-post targets are not reachable at all.

Neither mode ever fabricates a value. A field VK does not return is `null`, and a failed extraction fails the run rather than producing placeholder data.

### Output

One dataset item per post:

```json
{
    "postId": "-22822305_1070789",
    "ownerId": -22822305,
    "authorId": -22822305,
    "author": {
        "id": -22822305,
        "type": "group",
        "name": "Кинопоиск",
        "screenName": "kinopoisk",
        "url": "https://vk.com/kinopoisk",
        "photo": "https://sun.userapi.com/…",
        "isVerified": true,
        "membersCount": 2100000
    },
    "text": "Post body…",
    "postedAt": "2024-06-01T09:30:00.000Z",
    "editedAt": null,
    "sourceUrl": "https://vk.com/wall-22822305_1070789",
    "stats": { "likes": 1240, "comments": 87, "reposts": 33, "views": 98000, "engagement": 1360 },
    "mediaTypes": ["photo", "video"],
    "mediaCount": 2,
    "attachments": [
        { "type": "photo", "id": "-22822305_457301", "url": "https://sun.userapi.com/…jpg", "width": 2560, "height": 1440, "sizes": [] },
        { "type": "video", "id": "-22822305_456789", "url": "https://vk.com/video-22822305_456789", "title": "Trailer", "durationSeconds": 132, "viewsCount": 45000 }
    ],
    "isRepost": false,
    "repostChain": [],
    "isPinned": false,
    "isAd": false,
    "geo": null,
    "postSource": { "type": "vk", "platform": null },
    "target": "kinopoisk",
    "targetType": "handle",
    "scrapedAt": "2024-06-02T11:00:00.000Z"
}
```

Attachment objects carry type-specific fields — `poll` has `question`/`answers`/`votesCount`, `link` has `url`/`title`/`description`, `doc` has `extension`/`sizeBytes`, and so on. Unmapped attachment types still appear with their `type`, `id` and `isKnownType: false`, so nothing is silently dropped. With `includeComments`, each post also gets a `comments` array whose entries carry the commenter, text, likes and nested `replies`.

### Limits and behaviour

- **Rate limits.** VK allows roughly 3 requests/second per user token; the Actor runs API requests one at a time and retries error code 6 with backoff.
- **Budgets.** `maxItems` counts posts, not requests, and is enforced globally across targets. Posts are de-duplicated by `ownerId_postId`.
- **Failure.** A run that stores zero posts fails with a diagnostic message instead of finishing "successfully" with an empty dataset. An invalid or expired token fails the run immediately.
- **Scope.** Only public walls, or walls the supplied token can read. This Actor does not attempt to access private profiles or bypass VK's access controls.

### Development

```bash
npm install
npm test     # unit + handler tests, no network access
npm run lint
apify run    # requires an INPUT in storage/key_value_stores/default/
```

# Actor input Schema

## `vkTargets` (type: `array`):

VK walls to scrape. Accepts a public handle (`durov`), a profile or community URL (`https://vk.com/kinopoisk`), a signed owner ID (`-40316705`), or a direct post link (`https://vk.com/wall1_45678`).

## `accessToken` (type: `string`):

VK API access token with the `wall` scope. Strongly recommended: with a token the Actor uses the official VK API and returns every field (attachment URLs, view counts, exact timestamps, repost chains, comments). Without one it falls back to limited public HTML scraping.

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

Hard cap on the number of posts stored across all targets.

## `postsPerTarget` (type: `integer`):

Optional per-target cap. Leave empty to let each target use the shared budget.

## `publishedAfter` (type: `string`):

Only keep posts published at or after this date. `YYYY-MM-DD` or a full ISO-8601 timestamp. Pagination stops once older posts are reached.

## `publishedBefore` (type: `string`):

Only keep posts published at or before this date. A bare `YYYY-MM-DD` includes the whole day.

## `postFilter` (type: `string`):

Which posts to read from the wall. API mode only.

## `includeComments` (type: `boolean`):

Fetch comment threads (including replies) for every post. Requires an access token and makes the run noticeably slower.

## `maxComments` (type: `integer`):

Upper bound on comments fetched per post when "Include comments" is on.

## `keepUndatedPosts` (type: `boolean`):

Without an access token VK sometimes hides a post's date. By default such posts are dropped when a date filter is set, because they cannot be checked against it. Turn this on to keep them (their `postedAt` will be null and they may fall outside your date range).

## `htmlTimezone` (type: `string`):

Only used without an access token. VK prints post times in the viewer timezone, so the browser is pinned to this zone and the printed times are interpreted in it. Change it only if you want timestamps resolved as another region would see them.

## `includeRawPost` (type: `boolean`):

Attach the unmodified VK API object as `rawPost` on every item. Useful for fields this Actor does not map yet.

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

VK blocks most datacenter IP ranges. Residential proxies are used by default.

## Actor input object example

```json
{
  "vkTargets": [
    "kinopoisk",
    "durov"
  ],
  "maxItems": 500,
  "postFilter": "all",
  "includeComments": false,
  "maxComments": 100,
  "keepUndatedPosts": false,
  "htmlTimezone": "Europe/Moscow",
  "includeRawPost": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (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 = {
    "vkTargets": [
        "kinopoisk",
        "durov"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("molded_mountainpass/my-actor-2").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 = { "vkTargets": [
        "kinopoisk",
        "durov",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("molded_mountainpass/my-actor-2").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 '{
  "vkTargets": [
    "kinopoisk",
    "durov"
  ]
}' |
apify call molded_mountainpass/my-actor-2 --silent --output-dataset

```

## MCP server setup

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

```

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/HyPa5i5j9PWrseXOb/builds/Dz9vjuOEvQDSgvQ1T/openapi.json
