Perchance Stable Diffusion MCP Server
Bypasses Cloudflare challenges for the Perchance Stable Diffusion image generation service using curl_cffi and SeleniumBase UC Mode.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Perchance Stable Diffusion MCP Servergenerate an image of a futuristic city skyline at sunset"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Perchance Stable Diffusion MCP Server
MCP server for https://perchance.org/stable-diffusion-ai - Free, no sign-up, no limits Stable Diffusion generator.
Built after deep reverse-engineering of Perchance's actual APIs. Provides 15 tools for image generation via fully open-source unlimited self-hosted stack (no Browserless, no API keys, no limits).
๐ Open-Source Unlimited Stack (2026-09-24 Breakthrough) โ TESTED WORKING
Solution: curl_cffi + SeleniumBase UC Mode bypasses Cloudflare & Turnstile unlimited free, no proxy, no API key.
from curl_cffi import requests
r = requests.get("https://perchance.org/api/getAccessCodeForAdPoweredStuff",
impersonate="chrome",
headers={"Referer":"https://perchance.org/stable-diffusion-ai","Origin":"https://perchance.org"})
# 200 OK 64 hex: b0023d06ec6433f8ff9b4d2bef4dc91d9102c05f7fbc17b1a149a1a6be7c7d6f
# No proxy, unlimitedโ Ad code bypass: 100% working unlimited, no proxy (curl_cffi TLS impersonation)
โ Turnstile solving: SeleniumBase UC Mode (Chromium undetected) - TESTED, generates userKey 64 hex valid ~30s
โ Generate/download bypass: Same TLS impersonation works
โ Full generation proof:
opensource_cat.jpeg42k,opensource_landscape.jpeg66k๐ Full guide:
OPENSOURCE_GUIDE.md
MCP Tools (15, all open-source unlimited):
get_ad_code_opensource- Unlimited ad code via curl_cffiget_opensource_status- Check self-hosted stackgenerate_image_opensource- Main tool: Unlimited generation (curl_cffi + SeleniumBase UC) โrefresh_user_key_opensource- Unlimited userKey via self-hostedgenerate_image- Standard generation (requires fresh userKey)generate_image_official- Official API v1 (iframe + postMessage, permanent URLs)generate_image_embed- Embed API via PlaywrightPlus 8 more tools for styles, verification, batch, download
Built after deep reverse-engineering of Perchance's actual APIs. Fully open-source unlimited, no Browserless needed.
Related MCP server: cf-image-gen MCP Server
๐ฌ Research Summary - How Perchance Works (Updated 2026-09-24)
Two APIs Discovered
1. Official Image API v1 (Recommended for external apps)
Endpoint: https://perchance.org/perchance-ai-api
Docs: https://perchance.org/perchance-ai-api
Method: iframe + postMessage, no keys, permanent URLs
// 1) warm up once per user โ visits perchance.org so Cloudflare passes them
function warmUp() {
return new Promise(res => {
var f = document.createElement("iframe");
f.src = "https://perchance.org";
f.onload = () => { f.remove(); res(true); };
document.body.appendChild(f);
});
}
// 2) generate + cache (images are permanent URLs on user.uploads.dev โ never challenged)
function generateImage(prompt, opts) {
return new Promise((resolve, reject) => {
var p = new URLSearchParams({ prompt, format: "json", id: Math.random().toString(36).slice(2) });
if (opts) Object.keys(opts).forEach(k => p.set(k, opts[k]));
var f = document.createElement("iframe");
f.src = "https://perchance.org/perchance-ai-api?" + p;
function onMsg(e) {
var d = e.data || {};
if (d.api !== "perchance-image-api" || !d.result || d.result.id !== p.get("id")) return;
finish(d.result.ok ? resolve : reject, d.result);
}
window.addEventListener("message", onMsg);
document.body.appendChild(f);
});
}
warmUp().then(() => generateImage("a cute cat", { resolution: "768x768", seed: 7 }))
.then(r => { imgEl.src = r.url; }); // r = { ok, url, seed, dataUrl, ... }Parameters:
prompt,negativePrompt,resolution(512x512|512x768|768x512|768x768),guidanceScale(1-30),seed,removeBackground,format(html|json|redirect)Result: Permanent
user.uploads.devURLs, never challenged, cacheable
2. Internal API (Used by stable-diffusion-ai generator, faster, more control)
Endpoints:
https://image-generation.perchance.org/api/verifyUser?browserId=...&token=...&thread=...https://image-generation.perchance.org/api/checkUserVerificationStatus?userKey=...https://image-generation.perchance.org/api/generate?userKey=...&requestId=...&adAccessCode=...&v=...https://image-generation.perchance.org/api/downloadTemporaryImage?imageId=...(legacy)https://image-generation.perchance.org/api/downloadTemporaryImageViaProxy?t=v1....(new, quick-tunnel backend)https://perchance.org/api/getAccessCodeForAdPoweredStuff
Flow (Updated 2026-09-24):
Browser Identity:
localStorage['generation-v2-browser']= 32-char hex browserIdgeneration-identity-v2.jshandles this:[...crypto.getRandomValues(new Uint8Array(16))].map(n => n.toString(16).padStart(2,'0')).join('')Stores userKey as
localStorage['generation-v2:{browserId}:userKey-{thread}']= 64-char hex
Ad Access Code:
GET https://perchance.org/api/getAccessCodeForAdPoweredStuff?__cacheBust=...โ 64-char hexNEW: Now requires full headers (UA, Referer: https://perchance.org/stable-diffusion-ai, Origin: https://perchance.org) and proxy in some regions, else returns Cloudflare Just a moment challenge
Implemented with curl fallback in client.py because httpx TLS fingerprint gets blocked
Verification (Turnstile):
Tokenless:
GET /api/verifyUser?browserId={32hex}&thread=0&__cacheBust=...โ{"status":"failed_verification","reason":"token_required"}oralready_verifiedWith token: Loads Turnstile from
https://challenges.cloudflare.com/turnstile/v0/api.jswith sitekey0x4AAAAAAAA8g8NphwaSOT59Solves Turnstile, gets token, then
GET /api/verifyUser?browserId={32hex}&token={turnstileToken}&thread=0โ{"status":"success","userKey":"64hex"}GET /api/checkUserVerificationStatus?userKey={64hex}โ{"status":"verified"}ornot_verifiedNEW: userKey is IP-bound and short-lived (~30s), expires quickly, bound to residential IP
Generation (Updated):
POST /api/generate?userKey={64hex}&requestId=0.{random}&adAccessCode={64hex}&v=9b43eec2e71907610e4e9317b54c208495f6850086e92239a869811d2e2d77ee&__cacheBust=...v hash changed 2026-09-24: from
f4fd5ce3a6a768bf12d73c3d6a678d1fb5811e4a24b41c7964a13dc789c811cdto9b43eec2e71907610e4e9317b54c208495f6850086e92239a869811d2e2d77ee(extracted from embed JS)Body:
{prompt, negativePrompt, seed, resolution, guidanceScale, channel:"stable-diffusion-ai", subChannel:"public", userKey, adAccessCode, requestId}Responses:
{"status":"success","imageId":"...","fileExtension":"jpeg","seed":123,"imageDownloadUrl":"/api/downloadTemporaryImageViaProxy?t=v1....",...}โ NEW proxy download URL{"status":"success","imageDataUrls":["data:image/jpeg;base64,..."]}โ direct data URL{"status":"invalid_key"}โ key expired, need refresh{"status":"invalid_access_code"}โ refresh ad code{"status":"waiting_for_prev_request_to_finish"}โ wait 8s retry{"status":"client_update_required"}โ v hash outdated, need update
Download (Updated):
Legacy:
/api/downloadTemporaryImage?imageId=...NEW:
/api/downloadTemporaryImageViaProxy?t=v1.Tyl8PPYSXrs1EMop.sUSxeY...(37541 bytes JPEG, headers: X-Perchance-Proxy-Backend: quick-tunnel, X-Image-Sha256, X-Expires-At)Token is IP-bound, single-use, expires in ~5 minutes, requires cf_clearance cookie
Implemented with fallback: try proxy_download first, then imageId, then Playwright fetch inside page context to handle cookies
Embed:
https://image-generation.perchance.org/embed#JSONwhere JSON contains prompt etc. Embed postspostMessage({type:"finished", dataUrl, seedUsed, id})to parent.NEW: Embed JS now includes
hiddenSafeWaitworker timer to handle hidden tab throttling,paintTickfix for backgrounded tabs, andreportImageDownloadFailurebeacon
Frontend: https://perchance.org/stable-diffusion-ai imports
t2i-framework-plugin-v2which importstext-to-image-pluginwhich creates iframe to embed.
Cloudflare Challenges (Updated)
Both perchance.org and image-generation.perchance.org use Cloudflare managed challenges:
Embed page (
/embed) - returns challenge HTML withJust a moment...initially, then real content after JS challenge solves. Title becomesPerchance Image Generation EmbedwithwaitingEl.API endpoints (
/api/verifyUser,/api/generate,/api/getAccessCodeForAdPoweredStuff,/api/checkUserVerificationStatus) - now often return 403 Just a moment challenge for datacenter IPs, even after embed passed. Requires proxy + full headers + cf_clearance.Ad code endpoint - now blocked without proxy (returns Just a moment challenge), works via Webshare proxy
31.59.20.176:6754with UA+Referer+Origin+Accept headers. httpx still gets 403 due to TLS fingerprint, curl fallback works.Download proxy endpoint - returns 403 if token expired, IP mismatch, or missing cf_clearance cookie. Must be fetched inside Playwright page context that has clearance.
Error 600010: Turnstile generic challenge failure - bot behavior detected.
Workarounds implemented:
get_ad_access_code()tries httpx then curl fallback with full headers and proxydownload_image()tries httpx first, then Playwright fetch with cf_clearance_find_proxy_download()recursively finds proxy token in generate response (from eeemoon/perchance PR #9)CLIENT_VERSION_HASHupdated to9b43eec2e71907610e4e9317b54c208495f6850086e92239a869811d2e2d77eePlaywright with
playwright-stealthandLD_LIBRARY_PATHfix for E2B sandboxSync Playwright works better than async in sandbox (async gets EPIPE after 90s)
For local use, no proxy needed, residential IP passes Cloudflare
eeemoon/perchance Fix Applied
From https://github.com/eeemoon/perchance/pull/9 (Fix Perchance proxy image downloads):
Support new token-based
/downloadTemporaryImageViaProxyendpointRecursively discover proxy download URLs or v1 tokens in image generation responses
Keep previous
/downloadTemporaryImage?imageId=...as fallbackImplemented in
client.pyas_find_proxy_download()and updateddownload_image()
๐ ๏ธ Tools Provided (11 tools)
list_styles- List 76 art styles from t2i-styles (Cinematic, Anime, Oil Painting, etc.)get_generator_info- Info about generator, APIs, resolutions, how it works, env vars, notes (includes new v hash and proxy download)get_user_key_status- Check cached browserId and userKey validityrefresh_user_key- Try to obtain userKey via browser (may fail in sandbox with 600010, then manual instructions)verify_with_token- NEW Verify with browserId and Turnstile token to get fresh userKey (valid ~30s, IP-bound)generate_image- Generate via INTERNAL API (fastest, requires userKey, supports art styles, saves to file, now supports proxy_download token)generate_image_official- Generate via OFFICIAL API v1 (no key, permanent URLs on user.uploads.dev, iframe+postMessage)generate_image_embed- NEW Generate via embed page directly using Playwright (most reliable locally, handles Turnstile)generate_batch- Generate multiple images (supports both APIs)download_image_tool- Download by imageId or proxy_token (v1....)get_ad_code- Get current ad access code (public, 64 hex, now with curl fallback)
๐ฆ Installation
pip install -r requirements.txt
playwright install chromium
# If in E2B sandbox or missing libs:
bash install_deps.sh
export LD_LIBRARY_PATH=/tmp/debs/out/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH๐ Usage as MCP Server
Add to your MCP client config (e.g. Claude Desktop, Cursor, etc.):
{
"mcpServers": {
"perchance": {
"command": "python",
"args": ["/path/to/perchance-mcp/server.py"],
"env": {
"PERCHANCE_USER_KEY": "your-64-char-hex-key-optional-but-recommended-for-sandbox",
"PERCHANCE_PROXY": "http://user:pass@host:port-optional-for-sandbox"
}
}
}
}Or run directly:
python server.py
# or
bash run.sh๐ Manually Obtaining userKey and Turnstile Token
If refresh_user_key fails with Turnstile 600010 or 403:
userKey (64 hex, IP-bound, ~30s expiry):
Open https://perchance.org/stable-diffusion-ai in Chrome/Firefox (real browser, not headless)
Open DevTools > Application > Local Storage
Check
https://image-generation.perchance.orgorhttps://c0c3b93a12cdb77c30974f19f33289a7.perchance.orgFind key like
generation-v2:{browserId}:userKey-0with 64 hex chars valueCopy value and set env var:
export PERCHANCE_USER_KEY="abc123...64chars"
echo "abc123...64chars" > ~/.perchance-mcp/user_key.txtTurnstile Token (for fresh userKey):
Open https://perchance.org/stable-diffusion-ai in real browser
DevTools > Network tab, filter
verifyUserGenerate an image
Find request like
verifyUser?browserId=fa2e9a...&token=0.XXXX...&thread=0- copy token param (long string)Use tool
verify_with_tokenwith browserId and token within 30 seconds, from same IP (run MCP locally)
Then generate_image will work via HTTP.
๐ก Example Prompts
"a tiny robot watering a houseplant, cinematic lighting"
"cyberpunk city at night, neon lights, rain"
"Studio Ghibli style forest spirit"
"a cute cat pixel art"
Use with art styles:
art_style="Cinematic"- cinematic shot, dynamic lighting, 75mm, Technicolorart_style="Anime"- anime art, masterpiece, 4kart_style="Oil Painting"- oil on canvas, masterpieceart_style="Pixel Art"- 16-bit, 128pxSee
list_stylesfor all 76 styles
๐ Files
client.py- Core Perchance API client (both internal and official APIs, handles ad code with curl fallback, userKey, verification, generation with new v hash, download with proxy token, styles, LD_LIBRARY_PATH fix, _find_proxy_download from eeemoon)server.py- MCP server with 11 tools (FastMCP, includes new verify_with_token and generate_image_embed)styles.json- 76 art styles parsed from t2i-styles generatorcli.py- CLI for testingrun.sh- Runner with LD_LIBRARY_PATH fixinstall_deps.sh- Install chromium deps manually for sandboxmcp_config.json- Example MCP config with proxyrequirements.txt- Dependencies
๐งช Testing
# Test ad code (should work even in sandbox via curl fallback)
python -c "import asyncio; from client import get_ad_access_code; print(asyncio.run(get_ad_access_code()))"
# Test userKey status
python -c "import asyncio, json; from server import get_user_key_status; print(asyncio.run(get_user_key_status()))"
# Test generation (requires valid userKey, best run locally)
python cli.py "a cute cat" --style Cinematic --resolution 768x768
python cli.py "a cute cat" --official --output cat.jpg
python cli.py "a cute cat" --embed --output cat_embed.jpgโ ๏ธ Notes (Updated)
Sandbox limitation: In E2B or datacenter IPs, Cloudflare blocks embed and official API with 403, and Turnstile fails. Internal API HTTP generation still works if you provide valid
PERCHANCE_USER_KEYandPERCHANCE_PROXY. Sync Playwright works better than async (async gets EPIPE after 90s).v hash updated:
CLIENT_VERSION_HASHchanged 2026-09-24 to9b43eec2e71907610e4e9317b54c208495f6850086e92239a869811d2e2d77ee- old hashf4fd5ce3...now returnsclient_update_requiredNew download endpoint:
/api/downloadTemporaryImageViaProxy?t=v1....replaces imageId method, uses quick-tunnel backend, IP-bound, single-use, ~5min expiry, requires cf_clearance cookie - implemented with Playwright fallbackAd code now requires proxy: Without proxy returns Just a moment challenge, with Webshare proxy
31.59.20.176:6754and full headers works via curl fallback (httpx still 403 due to TLS fingerprint)userKey IP-bound: Key
e6ccce59a4f2dd052d3569e7706a35879e030f305b64ba41377c01063139976afor browserIdfa2e9a2af105eca0e4f15ea2b7b35bc1is already_verified in residential but not_verified from sandbox/proxy, and generate returns invalid_key via proxy - proves need for fresh Turnstile token <30sPermanent URLs: Official API returns permanent
user.uploads.devURLs that are never challenged - cache them!Rate limits:
waiting_for_prev_request_to_finishmay occur if you spam - wait 8s and retry (handled automatically)
๐ License
MIT - For research/educational use. Perchance's terms apply for image generation. Respect their service.
๐ Credits
Perchance (https://perchance.org) for free unlimited AI image generation
Reverse-engineered from https://image-generation.perchance.org/embed (58k inline JS with verifyUser, hiddenSafeWait, paintTick, reportImageDownloadFailure)
Inspired by https://github.com/eeemoon/perchance and PR #9 (Fix Perchance proxy image downloads by NovaUnboundAi)
This server cannot be deployed
Maintenance
Related MCP Connectors
Generate, edit and upscale images with references, batch jobs, cost previews and original downloads.
Generate logos, social posts, app screenshots, comic panels & visual-novel assets from prompts.
Create images and videos from prompts, with options for image mixing, reference images, and start/โฆ
Uncensored image, image-to-video and chat generation for adult apps. OpenAI-compatible, pay per use.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceProvides image generation tools powered by OpenRouter, running on Cloudflare Workers.27 npmMIT
- FlicenseNot gradedqualityCmaintenanceGenerates images and videos from text prompts using Cloudflare Workers AI and Google Gemini models.-
- AlicenseNot gradedqualityBmaintenanceEnables image generation and editing via ChatGPT web without API keys, saving images locally with conversation-aware editing.12 npm2MIT
- AlicenseAqualityBmaintenanceEnables private, one-shot image generation and editing via a self-hosted ComfyUI, with a simple model-agnostic tool surface and results delivered directly to the client without server-side storage.81MIT