From 3d4142f9b492a8c20d50810af2537ba239038453 Mon Sep 17 00:00:00 2001 From: Jake Writer Date: Sat, 22 Aug 2026 23:13:59 -0600 Subject: [PATCH 1/2] Say why the mcp publish 404s, because npm will not MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `Publish npm (captchakraken-mcp)` failed on the 2026-08-23 release with: npm error 404 Not Found - PUT https://registry.npmjs.org/captchakraken-mcp npm error 404 The requested resource 'captchakraken-mcp@0.1.1' could not be npm error 404 found or you do not have permission to access it. The package exists. captchakraken-mcp@0.1.0 has been on npm since 2026-07-29, published by hand. What is missing is the TRUSTED PUBLISHER entry, which is scoped to one package name — the header of this file already says the `captchakraken` entry does not cover it — and npm reports that as a 404 on the PUT rather than as a permissions error. That wording is what makes it expensive: `captchakraken` published in the same run, from the same workflow, over the same OIDC, so every obvious reading (bad auth, broken release, wrong version) is wrong, and the one true reading is the one npm declines to state. So the step now checks whether the package exists after a failed publish and, if it does, prints the actual cause and the four clicks that fix it. It still fails — this is a real release failure, not something to wave through. No behaviour change on the success path: an already-published version still skips, a good publish still exits 0. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/publish.yml | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 0735b4d..818f32f 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -103,13 +103,40 @@ jobs: - name: Build run: npm run build - name: Publish (idempotent) + # The `else` branch is wrapped because npm reports "you are not the + # trusted publisher for this package" as a 404 on the PUT: + # + # npm error 404 Not Found - PUT https://registry.npmjs.org/captchakraken-mcp + # npm error 404 The requested resource 'captchakraken-mcp@0.1.1' could + # npm error 404 not be found or you do not have permission to access it. + # + # Which reads as "the package does not exist" — and it plainly does, at + # 0.1.0, published by hand in July. That wording cost a real diagnosis on + # 2026-08-23: `captchakraken` published in the same run, from the same + # workflow, with the same OIDC, so the obvious readings (bad auth, broken + # release) were all wrong. The one true reading is the narrowest one, and + # npm will not say it. + # + # Trusted publishers are scoped to ONE package name (see the header), so + # a package first published by hand has no entry until someone adds it. + # Say so, and keep failing. run: | VER=$(node -p "require('./package.json').version") if npm view "captchakraken-mcp@$VER" version >/dev/null 2>&1; then echo "captchakraken-mcp@$VER already published — skipping." - else - npm publish --access public --provenance + exit 0 + fi + if npm publish --access public --provenance; then + exit 0 + fi + if npm view captchakraken-mcp version >/dev/null 2>&1; then + echo "::error::captchakraken-mcp EXISTS on npm ($(npm view captchakraken-mcp version)) \ + but this workflow is not its trusted publisher, which npm reports as a 404 on the PUT. \ + Fix: npmjs.com -> captchakraken-mcp -> Settings -> Trusted Publisher -> GitHub Actions, \ + repository JWriter20/CaptchaKraken, workflow publish.yml. The captchakraken entry does \ + NOT cover this package. Then re-run this job." fi + exit 1 publish-pypi: name: Publish PyPI (captchakraken) From b743783b61f23124d5e5c6dbd03cf3907d12dbe8 Mon Sep 17 00:00:00 2001 From: Jake Writer Date: Sat, 22 Aug 2026 23:38:07 -0600 Subject: [PATCH 2/2] Registry pages: the logo, and descriptions that are still true MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The npm and PyPI pages describe a grid solver that needs vLLM. Both halves are out of date. It has read click, drag, slide, distorted-text and animated challenges across ten vendors for a while now, and the hosted API means a user can run no model at all — neither fact appeared on either page, which are the two pages someone reads before deciding whether to install it. npm captchakraken "reads the grid ... on vLLM" PyPI captchakraken "Given a screenshot of a captcha grid, it locates the tiles and returns the click plan" Descriptions now say what it does, keywords name the vendors people actually search for, and each README opens with a what-it-solves table taken from the root README rather than a new set of claims. ## The logo, as a PNG, from an absolute URL `docs/assets/logo-card.png` — the existing logo-dark.svg on the site's own #04121a background, rounded. Three constraints decided this and none of them allow the block the root README uses: * PyPI does not render SVG and only loads images from an allowlist of hosts. raw.githubusercontent.com is on it; a relative path is not a URL at all. * npm and PyPI both rewrite or drop relative image paths, and this is a monorepo, so `./docs/...` resolves to nothing from a package subdirectory. * A one-colour mark has to pick a background. Both registries default to light and npm also has a dark mode, so the card carries its own — which also makes it match captchakraken.com. Verified rather than assumed: readme_renderer (the exact renderer PyPI uses) keeps both the and the centering, and `twine check` passes on the built sdist. ## Versions captchakraken 2.6.0 -> 2.6.1 on both registries, captchakraken-mcp 0.1.1 -> 0.1.2. Metadata-only, but a registry cannot be updated without a version. PyPI also gains the Python versions it supports, the trove classifiers a chooser reads before the README, and Documentation/Source/Changelog links — its sidebar had one Homepage row. Co-Authored-By: Claude Opus 5 (1M context) --- docs/assets/logo-card.png | Bin 0 -> 37499 bytes js/README.md | 45 ++++++++++++++++++++++++++++++-------- js/package.json | 14 +++++++++--- mcp/README.md | 15 +++++++++---- mcp/package.json | 9 +++++--- python/README.md | 38 +++++++++++++++++++++++++++----- python/pyproject.toml | 25 +++++++++++++++++---- 7 files changed, 118 insertions(+), 28 deletions(-) create mode 100644 docs/assets/logo-card.png diff --git a/docs/assets/logo-card.png b/docs/assets/logo-card.png new file mode 100644 index 0000000000000000000000000000000000000000..bb2cfecc987f8bf3cb442b656ca0c85192c56e8d GIT binary patch literal 37499 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 R9B^ATgQu&X%Q~loCIDJd?V|ty literal 0 HcmV?d00001 diff --git a/js/README.md b/js/README.md index f297709..fcbf9af 100644 --- a/js/README.md +++ b/js/README.md @@ -1,9 +1,20 @@ -# captchakraken +

+ CaptchaKraken +

-The TypeScript browser driver for [CaptchaKraken](https://github.com/JWriter20/CaptchaKraken). -Hand it a Playwright/Puppeteer `Page`; it finds the captcha, reads the grid with -a fine-tuned **Qwen3.5-9B** vision model on **vLLM**, clicks human-like, and -verifies through to a token. +

captchakraken

+ +

+ A captcha solver for browser automation.
+ The TypeScript driver for CaptchaKraken. +

+ +Hand it a Playwright or Puppeteer `Page`. It finds the captcha, reads the whole +puzzle with a fine-tuned **Qwen3.5-9B** vision model, and clicks, drags, slides +or types human-like through to a token. + +Run the model on **your own hardware**, or point it at the **hosted API** and run +nothing at all. > Full docs — demo videos, accuracy, self-hosting — live in the main repo > **[CaptchaKraken](https://github.com/JWriter20/CaptchaKraken)**. @@ -15,9 +26,9 @@ npm install captchakraken ``` The package bundles the Python engine (`captchakraken`) and, on `postinstall`, -creates a local venv with its lightweight core deps so grid detection + the vLLM -planner work out of the box. It ships **no browser** — bring your own -Playwright-compatible launcher. +creates a local venv with its lightweight core deps, so tile detection and the +inference client work out of the box. It ships **no browser** — bring your own +Playwright-compatible launcher (camoufox and patchright both work). - Skip the Python bootstrap: `CAPTCHA_KRAKEN_SKIP_PYTHON_SETUP=1` - To **self-host** the model, run the repo's `setup.sh` (installs vLLM + weights). @@ -37,6 +48,22 @@ claude mcp add captchakraken -- npx -y captchakraken-mcp `create_api_key` writes the key and the endpoint to `~/.captchakraken/credentials`, which the client reads on its own — **no environment variables needed**. +## What it solves + +| Vendor | Puzzles | +|---|---| +| **reCAPTCHA** | 3×3 and 4×4 image grids, including the dynamic re-deal | +| **hCaptcha** | Image grids, click, drag, connect-the-path, tetris-fit, animated | +| **GeeTest** v3 + v4 | Slide, icon, nine, svg, gobang, iconcrush | +| **NetEase Yidun** | Jigsaw, picture-click, icon-click | +| **Tencent, Lemin, Prosopo** | Slide, cropped-image and grid flows | +| **BotDetect, MTCaptcha, Yandex** | Distorted text — read and typed, not clicked | +| **Cloudflare Turnstile** | Via the checkbox flow (free on the hosted API) | + +**44 puzzle types**, driven end to end in CI against generated fixtures on both +the TypeScript and Python ports. Animated challenges are recorded, sliced into +keyframes and answered with the frame the action belongs to. + ## Usage ```typescript @@ -49,7 +76,7 @@ await page.goto('https://www.google.com/recaptcha/api2/demo'); // Reads VLLM_BASE_URL + CAPTCHA_KRAKEN_API_KEY from the environment. const solver = new CaptchaKrakenSolver(); -await solver.solve(page); // detect → solve grid → click → verify +await solver.solve(page); // detect → read → act → verify await browser.close(); ``` diff --git a/js/package.json b/js/package.json index 3c86b4b..eead524 100644 --- a/js/package.json +++ b/js/package.json @@ -1,7 +1,7 @@ { "name": "captchakraken", - "version": "2.6.0", - "description": "Browser-agnostic Playwright/Puppeteer captcha solver. Detects the captcha, reads the grid with a fine-tuned Qwen3.5-9B vision model on vLLM, and clicks through to a token.", + "version": "2.6.1", + "description": "Captcha solver for Playwright and Puppeteer. Finds the captcha, reads the puzzle with a fine-tuned Qwen3.5-9B vision model, and clicks, drags, slides or types through to a token — reCAPTCHA, hCaptcha, GeeTest, NetEase Yidun, Tencent, Lemin, Prosopo, Turnstile and distorted text. Hosted API or self-hosted.", "main": "dist/index.js", "types": "dist/index.d.ts", "files": [ @@ -25,11 +25,19 @@ }, "keywords": [ "captcha", + "captcha-solver", "recaptcha", "hcaptcha", + "geetest", + "turnstile", + "yidun", + "tencent-captcha", "playwright", "puppeteer", - "automation", + "camoufox", + "browser-automation", + "scraping", + "anti-bot", "vllm", "qwen" ], diff --git a/mcp/README.md b/mcp/README.md index 5283ad7..a3842c7 100644 --- a/mcp/README.md +++ b/mcp/README.md @@ -1,8 +1,15 @@ -# captchakraken-mcp +

+ CaptchaKraken +

-The CaptchaKraken account, driven from an MCP client. It signs you in through -GitHub, mints and revokes API keys for the solving endpoint, and reads back what -you have spent. +

captchakraken-mcp

+ +

+ The CaptchaKraken account, driven from an MCP client. +

+ +It signs you in through GitHub, mints and revokes API keys for the solving +endpoint, and reads back what you have spent. **It does not solve captchas.** The key it mints is what does that, against the OpenAI-compatible endpoint at `api.captchakraken.com/v1`. diff --git a/mcp/package.json b/mcp/package.json index 1a2f431..5c8ac42 100644 --- a/mcp/package.json +++ b/mcp/package.json @@ -1,7 +1,7 @@ { "name": "captchakraken-mcp", - "version": "0.1.1", - "description": "MCP server for CaptchaKraken: sign in with GitHub, mint API keys for the Abyss model, and read your usage and spending.", + "version": "0.1.2", + "description": "MCP server for the CaptchaKraken account: sign in with GitHub, mint and revoke API keys for the captcha-solving endpoint, and read your usage and balance. Writes the key to disk so the solver needs no environment variables.", "type": "module", "author": "Jake Writer", "license": "SEE LICENSE IN LICENSE", @@ -25,7 +25,10 @@ "mcp", "model-context-protocol", "captcha", - "captchakraken" + "captchakraken", + "claude", + "api-keys", + "llm-tools" ], "bugs": { "url": "https://github.com/JWriter20/CaptchaKraken/issues" diff --git a/python/README.md b/python/README.md index 05f9fb7..524f23a 100644 --- a/python/README.md +++ b/python/README.md @@ -1,14 +1,42 @@ -# captchakraken +

+ CaptchaKraken +

-The Python engine + CLI behind [CaptchaKraken](https://github.com/JWriter20/CaptchaKraken): -OpenCV grid detection + a fine-tuned **Qwen3.5-9B** vision LoRA served on -**vLLM**. Given a screenshot of a captcha grid, it locates the tiles and returns -the click plan. Ships the `captchakraken` command. +

captchakraken

+ +

+ A captcha solver for browser automation.
+ The Python engine and CLI behind CaptchaKraken. +

+ +OpenCV tile detection plus a fine-tuned **Qwen3.5-9B** vision model. Give it a +screenshot of a captcha and it returns the plan to solve it — which tiles to +select, where to click, what to drag, how far to slide, or what text to type. +Ships the `captchakraken` command. + +Run the model on **your own hardware**, or point it at the **hosted API** and run +nothing at all. > For demo videos, accuracy numbers, the browser driver, and the full > self-hosting guide, see the main repo > **[CaptchaKraken](https://github.com/JWriter20/CaptchaKraken)**. +## What it solves + +| Vendor | Puzzles | +|---|---| +| **reCAPTCHA** | 3×3 and 4×4 image grids, including the dynamic re-deal | +| **hCaptcha** | Image grids, click, drag, connect-the-path, tetris-fit, animated | +| **GeeTest** v3 + v4 | Slide, icon, nine, svg, gobang, iconcrush | +| **NetEase Yidun** | Jigsaw, picture-click, icon-click | +| **Tencent, Lemin, Prosopo** | Slide, cropped-image and grid flows | +| **BotDetect, MTCaptcha, Yandex** | Distorted text — read and typed, not clicked | +| **Cloudflare Turnstile** | Via the checkbox flow (free on the hosted API) | + +**44 puzzle types**, driven end to end in CI against generated fixtures on both +the TypeScript and Python ports. Animated challenges are recorded, sliced into +keyframes and answered with the frame the action belongs to. + ## Install ```bash diff --git a/python/pyproject.toml b/python/pyproject.toml index 7104cba..682aeb8 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -4,8 +4,8 @@ build-backend = "hatchling.build" [project] name = "captchakraken" -version = "2.6.0" -description = "Self-hosted captcha solver: OpenCV grid detection + a fine-tuned Qwen3.5-9B vision LoRA served on vLLM." +version = "2.6.1" +description = "Captcha-solving engine and CLI: OpenCV grid detection plus a fine-tuned Qwen3.5-9B vision model, for image grids, click and drag puzzles, sliders, distorted text and animated challenges. Hosted API or self-hosted on vLLM." readme = "README.md" requires-python = ">=3.10" # Source-available, NOT GPL. The CaptchaKraken Source-Available License permits @@ -14,12 +14,26 @@ requires-python = ">=3.10" # — see LICENSE. (GPL-3.0 would wrongly permit all three.) license = { file = "LICENSE" } authors = [{ name = "Jake Writer" }] -keywords = ["captcha", "recaptcha", "hcaptcha", "vllm", "qwen", "computer-vision", "automation"] +keywords = [ + "captcha", "captcha-solver", "recaptcha", "hcaptcha", "geetest", "turnstile", + "yidun", "tencent-captcha", "playwright", "browser-automation", "scraping", + "anti-bot", "vllm", "qwen", "computer-vision", "ocr", +] classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Operating System :: OS Independent", "Topic :: Scientific/Engineering :: Artificial Intelligence", + "Topic :: Scientific/Engineering :: Image Recognition", + "Topic :: Internet :: WWW/HTTP :: Browsers", + "Topic :: Software Development :: Testing", "License :: Other/Proprietary License", + "Typing :: Typed", ] # Core = the lightweight CLIENT: OpenCV grid detection + the HTTP planner that @@ -55,8 +69,11 @@ dev = [ captchakraken = "captchakraken.cli:main" [project.urls] -Homepage = "https://github.com/JWriter20/CaptchaKraken" +Homepage = "https://captchakraken.com" +Documentation = "https://github.com/JWriter20/CaptchaKraken#readme" +Source = "https://github.com/JWriter20/CaptchaKraken" Issues = "https://github.com/JWriter20/CaptchaKraken/issues" +Changelog = "https://github.com/JWriter20/CaptchaKraken/blob/main/CHANGELOG.md" [tool.hatch.build.targets.wheel] packages = ["src/captchakraken"]