Duolingo on autopilot.

A runner that plays Duolingo in a real browser. It reads each exercise, works out the answer and clicks. Chess, math and every language course, around the clock.

Real solved exercises, replayed live and cycling tracks. Not a screenshot: it plays the move.

How it works

It reads the answer key.

Duolingo renders every exercise from a React component, and that component still holds the answer. pwnlingo walks the component tree from the visible widget up to the challenge props, reads the correct answer, and does what a very fast, very bored student would do. A shape it has never seen gets logged and skipped, never guessed.

One Node runner drives a real Chromium window, signed in as you. A browser-side solver handles language, chess and music, a second one handles math. Drags and chess moves use a real mouse, because Duolingo ignores synthetic ones.

It runs unattended for weeks, not minutes. Every course shows a completion percentage and a measured ETA, and finished tracks move on to the next. Balance mode plays whichever course is furthest behind instead of grinding one to 100% while the rest stall. Running out of hearts does not stop the run, a lesson that loops without finishing gets escaped, the runner pauses itself when the disk is nearly full, and a track that earns nothing is benched for a day.

Chess

Puzzles hand over the moves.

A puzzle carries its solution as a list of moves. The board is a canvas, so the runner converts squares to screen pixels and a real mouse plays them.

Matches against Duolingo's bot are played by Stockfish, with a bundled JavaScript engine as the fallback if Stockfish is missing.

When you see a good move, look for a better one.Emanuel Lasker

Where it stands

What works today.

MathSolvers for every unit type. A short list of stubborn levels is still open.
ChessPuzzles and bot matches both solved.
LanguagesChoice, word bank, typed, cloze, pairs, bare translate and stories. Walks the whole tree unattended.
AudioListen exercises are skipped, not guessed. Speaking exercises are spoken aloud on a Mac, and skipped when the screen has no record button, so a lesson is never thrown away.
QuestsChecks the quests page every half hour and claims finished rewards.

Finish line

Every course, at 100%.

The goal is simple: every language course on the account finished, then math and chess. The route there is measured, not guessed. A progress report reads the runner's own log and prints the pace and the days left to each checkpoint: an average course at 25%, 50%, 75% and 100%, and total XP at 500k, 750k and one million.

The dates live in the project roadmap and get re-measured every week, because the last courses run slower than the first.

Clients

Status app

A small app polls the runner over the LAN or the open internet. Chess renders as a real animated board with real chess pieces, sliding move to move. Language and math read the same way: the actual prompt, answer choices, and pattern tables, straight off the page's own elements. A screenshot only shows up for the rare widget type with nothing textual to read, like a geometry diagram. Track, XP, streak, hearts, league, and a real per-puzzle progress bar sit in a frosted glass panel below the board. Pause the runner from the app, switch tracks (any language course, plus math and chess) from its Track menu, no terminal needed.

Native everywhere, no web wrapper: Apple platforms in SwiftUI, Android and Windows and Linux in Compose Multiplatform, plus a terminal client. All of them read the same endpoints on the runner, so there is one source of truth and every client is just a view of it.

macOSSwiftUI. Live board, frosted panel, Track menu, pause. Menu bar extra shows live XP without opening a window.
iOSSwiftUI, same screen, over the LAN or the tunnel. Home screen widget for XP and streak.
watchOSA glance: XP, track, paused or stuck. Board and pause one tap deeper.
AndroidCompose Multiplatform. Sideloadable APK from CI.
WindowsCompose Desktop, packaged as an .msi.
LinuxCompose Desktop, packaged as a .deb.
Terminalpwnlingo-tui prints the current state and exits. Point it at the tunnel and check from anywhere over SSH.

Reads are open; pausing, switching track, and the fallback screenshot need a token, because the tunnel puts all of it on the public internet.

Why

A study, not a product.

It started as a way to keep a streak alive during a busy week and turned into a study of how much of a gamified app is actually the client grading itself. Automated play is against Duolingo's terms, and the XP still ranks you against real people, so this is a curiosity to read, not a product to run.