{"record":{"id":"f58e9df2b2b769f0","repo":"tonhowtf/omniget","slug":"o-cloudflare-do-letterboxd-barrou-o-download-abra-letterboxd","errorCode":null,"errorMessage":"o Cloudflare do Letterboxd barrou o download. Abra letterboxd.com no navegador, passe pelo \"Just a moment\" e capture os cookies de novo na extensão — o cf_clearance precisa vir junto","messagePattern":"o Cloudflare do Letterboxd barrou o download\\. Abra letterboxd\\.com no navegador, passe pelo \"Just a moment\" e capture os cookies de novo na extensão — o cf_clearance precisa vir junto","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/lists/letterboxd.rs","lineNumber":388,"sourceCode":"        _ => {\n            if !f.has_session() {\n                return Err(anyhow!(\n                    \"sem sessão do Letterboxd: capture os cookies de letterboxd.com na extensão, ou aponte um ZIP já baixado de letterboxd.com/settings/data/\"\n                ));\n            }\n            report(\n                &p,\n                TOOL_ID,\n                \"progress\",\n                0,\n                Some(3),\n                Some(EXPORT_URL.to_string()),\n            );\n            let (b, ctype) = f.get_bytes(EXPORT_URL).await?;\n            if ctype.contains(\"text/html\") || b.len() < 200 {\n                let body = String::from_utf8_lossy(&b);\n                if is_cloudflare_wall(&body) {\n                    return Err(anyhow!(\n                        \"o Cloudflare do Letterboxd barrou o download. Abra letterboxd.com no navegador, passe pelo \\\"Just a moment\\\" e capture os cookies de novo na extensão — o cf_clearance precisa vir junto\"\n                    ));\n                }\n                return Err(anyhow!(\n                    \"o Letterboxd devolveu uma página em vez do ZIP — a sessão salva expirou; capture os cookies de novo\"\n                ));\n            }\n            (b, EXPORT_URL.to_string())\n        }\n    };\n    if opts.keep_zip {\n        let _ = std::fs::write(dest.join(\"letterboxd-export.zip\"), &bytes);\n    }\n\n    // 2. Normalização.\n    report(\n        &p,\n        TOOL_ID,","sourceCodeStart":370,"sourceCodeEnd":406,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/lists/letterboxd.rs#L370-L406","documentation":"After downloading the Letterboxd data export ZIP, the tool checks whether the response is HTML or suspiciously small (<200 bytes) and runs is_cloudflare_wall on the body. If the content matches a Cloudflare challenge page ('Just a moment...'), it throws this error: Letterboxd's Cloudflare protection blocked the automated request because the captured cookies lack a valid cf_clearance token.","triggerScenarios":"Calling run without a local zip_path (so the tool downloads EXPORT_URL) while the session's cf_clearance cookie is missing, expired, or was issued for a different IP/user-agent; the download returns the Cloudflare interstitial instead of the ZIP.","commonSituations":"Cookies captured before passing the Cloudflare challenge; cf_clearance expired (it is short-lived and IP/user-agent bound); user switched networks/VPNs after capturing cookies; user-agent mismatch between the extension capture and the Fetcher's requests.","solutions":["Open letterboxd.com in the browser, solve the 'Just a moment' challenge, then re-capture cookies in the extension so cf_clearance is included, and re-run.","Make sure the capture happens on the same network/IP and with the same user-agent the Fetcher will use.","Prefer downloading the ZIP manually at letterboxd.com/settings/data/ and passing its path via opts.zip_path to bypass the automated download entirely.","Retry shortly after re-capturing; cf_clearance is time-limited, so run the tool soon after capture."],"exampleFix":"// before\nlet opts = Options { zip_path: None, session_netscape: Some(\"old_cookies.txt\".into()), .. };\nrun(&opts, p).await?; // hits Cloudflare wall\n// after\nlet opts = Options { zip_path: Some(\"./letterboxd-export.zip\".into()), .. };\nrun(&opts, p).await?; // manual download bypasses Cloudflare","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"match letterboxd::run(&opts, &p).await {\n    Err(e) if e.to_string().contains(\"Cloudflare\") => {\n        eprintln!(\"abra letterboxd.com no navegador, resolva o desafio, recapture os cookies e tente de novo\");\n        // fallback: peça ao usuário um ZIP baixado manualmente e rode com zip_path\n    }\n    other => other?,\n}","preventionTips":["Solve the 'Just a moment' challenge in the browser before capturing cookies","Capture cf_clearance on the same IP/network and user-agent the tool will use","Run the export soon after capturing — cf_clearance expires quickly","Avoid switching VPN/network between capture and run; or simply pass a manually downloaded ZIP via zip_path"],"tags":["cloudflare","letterboxd","anti-bot","http","cookies"],"backgroundTag":"cloudflare-challenge-blocked","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}