# Wikimedia Pageviews & Analytics Scraper (`scrapyx/wikimedia-pageviews-scraper`) Actor

Query the keyless Wikimedia Analytics API (AQS) for any Wikipedia project. Article and project pageviews over time, the top 1000 articles per day/month, views by country, unique devices, Commons media requests, and edit/editor activity. Legacy pagecounts back to 2007. CC0.

- **URL**: https://apify.com/scrapyx/wikimedia-pageviews-scraper.md
- **Developed by:** [Ibnu Adzim](https://apify.com/scrapyx) (community)
- **Categories:** Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.40 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Wikimedia Pageviews & Analytics Scraper

Query the **[Wikimedia Analytics API](https://doc.wikimedia.org/generated-data-platform/aqs/analytics-api/)**
(AQS) — the official, keyless analytics service for every Wikimedia project.
No login, no API key; pageview and analytics data is CC0.

- **Article pageviews** — daily / monthly views for any article, split by
  access method (desktop / mobile) and agent (user / spider / automated)
- **Project pageviews** — whole-project totals over time, down to **hourly**;
  windows before 2015-07-01 auto-route to **legacy pagecounts** (back to 2007)
- **Top articles** — the up-to-1000 most-viewed articles for a day or a month,
  ranked
- **Top by country** — which countries send a project the most traffic
  (privacy-bucketed by Wikimedia)
- **Unique devices** — Wikimedia's estimated unique-device counts per project
- **Media file requests** — request counts for Commons / `upload.wikimedia.org`
  files, per file or aggregated by referer / media type
- **Wiki activity** — edits, active editors, new pages and new registered
  users per project over time

| Record type | One per | Carries |
| --- | --- | --- |
| `SEARCH_SUMMARY` | work unit (article / date / month / file / metric) or the whole run | `rowsReturned`, `requestsMade`, date range, totals, `truncated`, `note` |
| `PAGEVIEWS` | timestamp bucket | project, article (or project total), access, agent, granularity, `timestamp`, `views`, `articleUrl` |
| `TOP_ARTICLE` | ranked article | project, access, date, `period`, `rank`, `article`, `views` |
| `COUNTRY` | country | project, `month`, `rank`, `country`, `viewsRange` (bucket), `viewsCeil` |
| `UNIQUE_DEVICES` | timestamp bucket | project, `accessSite`, `devices`, `offset`, `underestimate` |
| `MEDIA_REQUESTS` | timestamp bucket | `subMode`, `fileName`, `filePath`, `referer`, `mediaType`, `requests` |
| `WIKI_ACTIVITY` | timestamp bucket | project, `metric`, `editorType`, `pageType`, `value` |
| `ERROR` | bad input / unrecoverable fetch | `_error` + `_errorDetail` |

Every data row keeps the verbatim upstream item in `raw` (turn off with
`slimOutput`). Timestamps are normalised to a UTC ISO string — `YYYY-MM-DD`
for daily/monthly, `…T HH:00:00+00:00` for hourly.

### Modes & inputs

| Mode | Needs | Notes |
| --- | --- | --- |
| `article-pageviews` | `articles`, date range | `granularity` daily or monthly (hourly is a 400) |
| `project-pageviews` | date range | `granularity` also hourly; `project` may be `all-projects`; pre-2015 → legacy |
| `top-articles` | `dates` (`YYYY/MM/DD` or `YYYY/MM`) | up to 1000 ranked; not `all-projects`; defaults to last month |
| `top-by-country` | `months` (`YYYY/MM`) | views are privacy buckets, never exact; not `all-projects` |
| `unique-devices` | date range | `accessSite` = all-sites / desktop-site / mobile-site |
| `media-requests` | `files` (per-file) or just filters (aggregate) | `File:Name.jpg` is resolved to its hashed upload path |
| `wiki-activity` | `activityMetrics` | `edits`, `editors`, `new-pages`, `registered-users` |

### Things the AQS will mislead you about

Each is measured, and each has a scenario in
`tests/smoke/wikimedia-pageviews-scraper_traps.sh` (14/14 passing).

**One 404 body means four different things.** An unknown project, a title that
has never been viewed, a future date range and a range that is simply too
recent for the data to have landed all return the same
`{"detail": "…we either do not have data…"}`. This Actor treats that as a
**`SEARCH_SUMMARY` with `rowsReturned: 0` and a note**, never an error. (A
*different* 404, `{"detail": "invalid route"}`, means a real path bug and is
surfaced.)

**Article titles are case-sensitive.** `berlin` returns nothing; `Berlin`
returns data. Spaces and underscores are interchangeable; `/` in a title
(`AC/DC`) is handled for you.

**`top-by-country` never gives an exact number.** `viewsRange` is a bucket
string like `"1000000000-9999999999"`; `viewsCeil` is its upper bound.
Wikimedia buckets these for reader privacy.

**`top-articles` and `top-by-country` reject `all-projects`.** Only
`project-pageviews` accepts it.

**Two response shapes.** Pageviews / unique-devices / media-requests return a
flat `items` list. Edit metrics nest the series one level deeper under
`results` with ISO timestamps — normalised to the same row shape here.

**A bad enum value or `start > end` is an honest HTTP 400.** Bad enums are
caught client-side (with the valid set in the message) before a request is
spent; `start > end` is passed through as `bad_request`.

### Notes on cost

One request per article / per date / per month / per file / per metric; a
single request for `project-pageviews` and `unique-devices` (two when the
window straddles 2015-07-01). A multi-year daily series comes back in **one**
request. No proxy needed — the AQS has no anti-bot layer.

# Actor input Schema

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

Which AQS metric family to query. `article-pageviews` = views per article; `project-pageviews` = whole-project totals; `top-articles` = the most-viewed articles for a day/month; `top-by-country` = country breakdown; `unique-devices` = device estimates; `media-requests` = Commons/upload media hits; `wiki-activity` = edits/editors/new pages/new users.

## `project` (type: `string`):

Wikimedia project domain, e.g. `en.wikipedia`, `de.wikipedia`, `commons.wikimedia`, `www.wikidata`. For `project-pageviews` you may also use `all-projects` (not accepted by top-articles / top-by-country).

## `articles` (type: `array`):

`article-pageviews` mode. One article title per line — the EXACT title (case-sensitive; spaces or underscores both fine). E.g. `Berlin`, `Python (programming language)`, `AC/DC`.

## `startDate` (type: `string`):

Time-series modes (article / project / unique-devices / media-requests / wiki-activity). `YYYY-MM-DD` or `YYYYMMDD`. Defaults to 30 days ago (180 for wiki-activity). Modern pageview data begins 2015-07-01; earlier project-pageviews windows auto-route to legacy pagecounts (back to 2007-12).

## `endDate` (type: `string`):

Time-series modes. `YYYY-MM-DD` or `YYYYMMDD`. Defaults to today. The most recent 1-2 days of pageviews (and several days of edit metrics) may not have landed yet — that returns an empty summary with a note, not an error.

## `granularity` (type: `string`):

`daily` or `monthly` for every time-series mode; `hourly` additionally for `project-pageviews` and `media-requests`. per-article rejects hourly.

## `access` (type: `string`):

article / project / top-articles / top-by-country. `all-access`, or split by `desktop` / `mobile-web` / `mobile-app`.

## `agent` (type: `string`):

article / project pageviews. `all-agents`, or `user` (exclude bots/crawlers), `spider`, `automated`.

## `dates` (type: `array`):

`top-articles` mode. One per line: `YYYY/MM/DD` for a single day, or `YYYY/MM` for the whole-month ranking. Defaults to last month's whole-month ranking. Each date is one request; up to 1000 ranked articles come back.

## `months` (type: `array`):

`top-by-country` mode. One `YYYY/MM` per line. Defaults to last month. Views are privacy-bucketed (a range string + a ceiling), never exact.

## `maxTopArticles` (type: `integer`):

`top-articles` mode. Trim each day's/month's ranking to the top N (max and default 1000).

## `accessSite` (type: `string`):

`unique-devices` mode. `all-sites`, `desktop-site` or `mobile-site`.

## `mediaSubMode` (type: `string`):

`media-requests` mode. `per-file` = counts for specific files in `files`; `aggregate` = project-wide media requests split by referer / media type.

## `files` (type: `array`):

`media-requests` per-file. One per line: a Commons file name (`File:Wikipedia-logo-v2.svg` or just `Wikipedia-logo-v2.svg`) — resolved to its hashed upload path automatically — or a ready `/wikipedia/commons/8/80/Wikipedia-logo-v2.svg` path.

## `referer` (type: `string`):

`media-requests` mode. `all-referers`, `internal`, `external`, `search-engine`, `unknown`, `none`.

## `mediaType` (type: `string`):

`media-requests` aggregate sub-mode. `all-media-types`, `image`, `audio`, `video`, `document`, `other`.

## `activityMetrics` (type: `array`):

`wiki-activity` mode. Any of: `edits`, `editors`, `new-pages`, `registered-users`. Each is one request. Defaults to edits + editors + new-pages.

## `editorType` (type: `string`):

`wiki-activity` mode. `all-editor-types`, `anonymous`, `group-bot`, `name-bot`, `user`.

## `pageType` (type: `string`):

`wiki-activity` mode. `all-page-types`, `content` (article namespace), `non-content`.

## `activityLevel` (type: `string`):

`wiki-activity` mode, `editors` metric only. `all-activity-levels`, `1..4-edits`, `5..24-edits`, `25..99-edits`, `100..-edits`.

## `slimOutput` (type: `boolean`):

By default every data row carries the verbatim upstream item in `raw`. Turn on to emit only the normalised fields.

## `maxResults` (type: `integer`):

Global cap on data rows across the whole run (summaries and errors don't count). Default 100,000.

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

Parallel in-flight requests (matters for article / top / media / wiki-activity modes with many inputs).

## `minRequestInterval` (type: `number`):

Politeness pacing for Wikimedia's infrastructure. The AQS is generous but shared.

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

Optional. No anti-bot layer on the AQS, so a proxy is OFF by default.

## Actor input object example

```json
{
  "mode": "article-pageviews",
  "project": "en.wikipedia",
  "articles": [
    "Berlin",
    "Python (programming language)"
  ],
  "granularity": "daily",
  "access": "all-access",
  "agent": "all-agents",
  "maxTopArticles": 1000,
  "accessSite": "all-sites",
  "mediaSubMode": "per-file",
  "referer": "all-referers",
  "mediaType": "all-media-types",
  "activityMetrics": [
    "edits",
    "editors",
    "new-pages"
  ],
  "editorType": "all-editor-types",
  "pageType": "all-page-types",
  "activityLevel": "all-activity-levels",
  "slimOutput": false,
  "maxResults": 100000,
  "maxConcurrency": 4,
  "minRequestInterval": 0.15,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `items` (type: `string`):

One row per scraped record. See the dataset's default view for field definitions.

# 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 = {
    "project": "en.wikipedia",
    "articles": [
        "Berlin",
        "Python (programming language)"
    ],
    "activityMetrics": [
        "edits",
        "editors",
        "new-pages"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapyx/wikimedia-pageviews-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 = {
    "project": "en.wikipedia",
    "articles": [
        "Berlin",
        "Python (programming language)",
    ],
    "activityMetrics": [
        "edits",
        "editors",
        "new-pages",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("scrapyx/wikimedia-pageviews-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 '{
  "project": "en.wikipedia",
  "articles": [
    "Berlin",
    "Python (programming language)"
  ],
  "activityMetrics": [
    "edits",
    "editors",
    "new-pages"
  ]
}' |
apify call scrapyx/wikimedia-pageviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scrapyx/wikimedia-pageviews-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/WVRDffRdsY5dviuz1/builds/ZNwwC3VTeHIFdD0Q1/openapi.json
