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 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.
Generate images with your own ChatGPT subscription (Plus, Pro or Team), without spending API credits
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceProvides image generation tools powered by OpenRouter, running on Cloudflare Workers.52 npmMIT
- FlicenseNot gradedqualityBmaintenanceGenerates images and videos from text prompts using Cloudflare Workers AI and Google Gemini models.-
- AlicenseNot gradedqualityCmaintenanceEnables image generation and editing via ChatGPT web without API keys, saving images locally with conversation-aware editing.10 npm2MIT
- AlicenseAqualityCmaintenanceEnables 0-credit AI image generation and credit-billed video generation (Veo/abra) through your local Chrome session, requiring no API keys or third-party proxies.428 npmMIT