Skip to content

[SaveFileView] All PCGamingWiki requests fail with HTTP 403 – Cloudflare now requires a User-Agent header #749

Description

@tiggadry

Note: I used GitHub Copilot to help investigate and write up this report. The diagnosis and the PowerShell proof below are real and verified on my machine — I just had AI assistance figuring out why it was broken.


Extension name

Save File View

Bug Description

Since approximately late April 2026, all PCGamingWiki data fetching silently fails, resulting in:

Done. Obtained data from 0 game(s). Could not obtain data of N game(s).

This happens both for bulk "Refresh directories from PCGamingWiki" (all games) and for individual single-game refreshes. Previously downloaded/cached JSON files continue to work fine — only new HTTP requests to PCGamingWiki fail.

Root Cause

PCGamingWiki is protected by Cloudflare, which now blocks HTTP requests that do not include a User-Agent header (returns HTTP 403 Forbidden with a Cloudflare block page).

FlowHttp's HttpRequestFactory.GetHttpRequest().WithUrl(uri).DownloadString() sends requests without any User-Agent header by default. Cloudflare treats these as bots and blocks them.

This is consistent with the PCGamingWiki API developer notice from April 26, 2026: "Additional caching + rate limiting have been applied and may affect you if you interface with the MediaWiki API."

Proof

Tested directly using .NET HttpClient (same as FlowHttp uses internally):

Without User-Agent → HTTP 403:

Add-Type -AssemblyName System.Net.Http
$url = "https://www.pcgamingwiki.com/w/api.php?action=cargoquery&tables=Infobox_game&fields=_pageName%3DPageID%2CSteam_AppID&where=Steam_AppID+HOLDS+%221091500%22&format=json"
$client = New-Object System.Net.Http.HttpClient
$response = $client.GetAsync($url).Result
Write-Host "HTTP Status: $($response.StatusCode)"
# Output: HTTP Status: Forbidden

With User-Agent → HTTP 200 OK + valid JSON:

$client.DefaultRequestHeaders.Add("User-Agent", "SaveFileView/1.0 (Playnite Plugin; https://github.com/darklinkpower/PlayniteExtensionsCollection)")
$response = $client.GetAsync($url).Result
Write-Host "HTTP Status: $($response.StatusCode)"
$client.GetAsync($url).Result.Content.ReadAsStringAsync().Result
# Output: HTTP Status: OK
# {"cargoquery":[{"title":{"PageID":"Cyberpunk 2077","Steam AppID":"1091500,..."}}]}

Proposed Fix

Add a User-Agent header to all PCGamingWiki HTTP requests in SaveFileView.cs. The PCGamingWiki API docs recommend the format: clientname/version (contact info) framework/version

// Before (broken since Cloudflare enforcement):
HttpRequestFactory.GetHttpRequest()
    .WithUrl(uri)
    .DownloadString();

// After:
HttpRequestFactory.GetHttpRequest()
    .WithUrl(uri)
    .WithHeaders(new Dictionary<string, string> {
        { "User-Agent", "SaveFileView/1.0 (Playnite Plugin; https://github.com/darklinkpower/PlayniteExtensionsCollection)" }
    })
    .DownloadString();

This affects all three places in SaveFileView.cs that call the PCGamingWiki API:

  • GetPcgwPageId (cargo query by Steam/GOG AppID)
  • GetPcgwPageIdBySearch (search query fallback)
  • GetWikiTextForPageId (wikitext download)

Additional note: Rate limiting for bulk refresh

The PCGamingWiki API also enforces a 30 requests/minute rate limit. When refreshing hundreds of games at once, this will cause HTTP 429 responses after the first ~15 games (each game requires ~2 requests). Consider adding a small delay between requests in RefreshGamesDirectories to stay under the limit.

To Reproduce

  1. Delete the SaveFileView data folder: %AppData%\Playnite\ExtensionsData\f68f302b-9799-4b77-a982-4bfca97130e2\
  2. Select any game(s) with a Steam AppID in Playnite
  3. Right-click → Game menu → SaveFileView: Refresh directories from PCGamingWiki
  4. Result: "Done. Obtained data from 0 game(s)."

Expected Behavior

PCGamingWiki data is fetched successfully and JSON files are created in the data folder.

Environment

  • Plugin version: 2.22
  • Playnite version: 10.55
  • OS: Windows 11 Home
  • PCGamingWiki change: Cloudflare User-Agent enforcement active as of ~April 26, 2026

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions