PageSourceSearch

https://langladder.com/privacy

html langladder.com collected 2026-10-02 01:33:50 UTC 12,196 bytes, 38 lines download raw bytes

1<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Schibsted+Grotesk:wght@400;500;600;700&amp;family=DM+Mono:wght@400;500&amp;display=swap" data-precedence="default"/><link rel="stylesheet" href="/assets/app-BKAKdFEN.css" data-precedence="default"/><title>Privacy Policy — Langladder</title><meta name="description" content="Free Chrome extension that rewrites the webpages you already read into the language you’re learning, graded to your level — with word glosses and flashcards."/><link rel="modulepreload" href="/assets/index-Dx81JACi.js"/><link rel="modulepreload" href="/assets/privacy-D7wBcKxu.js"/><link rel="modulepreload" href="/assets/legal-BIgB7SzV.js"/><link rel="icon" href="/favicon.svg" type="image/svg+xml"/><link rel="preconnect" href="https://fonts.googleapis.com"/><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="anonymous"/></head><body><!--$--><nav class="nav"><div class="container nav-inner"><a aria-label="Langladder home" href="/" class="logo"><span class="logo-mark"><span></span><span></span><span></span></span><span class="logo-word">Langladder</span></a><div class="nav-links"><a href="#why">Why it works</a><a href="#vocab">Flashcards</a><a href="#languages">Languages</a></div><div class="nav-right"><a href="/login" class="nav-login">Log in</a><a class="btn btn-primary nav-cta" href="https://chromewebstore.google.com/detail/langladder/mmgffnjkdbphaphfidomllbpjpekklmo" target="_blank" rel="noopener"><svg viewBox="0 0 48 48" width="16" height="16" aria-hidden="true" class="chrome-icon"><path fill="#EA4335" d="M0 24a24 24 0 0 1 48 0Z"></path><path fill="#34A853" d="M0 24a24 24 0 0 0 24 24V24Z"></path><path fill="#FBBC05" d="M24 48a24 24 0 0 0 24-24H24Z"></path><g stroke="#fff" stroke-width="3"><path d="M1 24H47"></path><path d="M24 24V47"></path></g><circle cx="24" cy="24" r="13" fill="#fff"></circle><circle cx="24" cy="24" r="10" fill="#4285F4"></circle></svg>Add to Chrome</a></div></div></nav><main><div class="container"><article class="legal"><header class="legal-head"><span class="eyebrow">Legal</span><h1>Privacy Policy</h1><p class="legal-updated">Last updated <!-- -->September 12, 2026</p></header><div class="legal-body"><p class="legal-intro">Langladder rewrites the webpages you already read into your target language at your chosen level. This policy explains what we collect, why, and the choices you have. We try to collect as little as possible.</p><h2>What we collect</h2><ul><li><strong>Account information.</strong> When you create an account we store your email address and name, and a securely hashed password. If you sign in through a third-party account, we receive basic profile information (such as your name, email, and avatar) from that provider instead of a password.</li><li><strong>Page text you choose to translate.</strong> When you translate a page, the visible text on that page is sent to our servers and to our AI service, OpenRouter, and the third-party model providers it routes to, to produce the rewrite. Langladder uses it to generate that translation and does not store the page contents afterward. Providers process submitted text under their own retention and privacy policies.</li><li><strong>Words you save.</strong> Vocabulary you save for review — the word, its definition, the surrounding sentence, and the target language and level — is stored in your account so you can review it later. When you save from the Chrome extension, the source page URL is also stored with the card.</li><li><strong>Operational data.</strong> We keep limited request metadata (such as counts used to enforce rate limits) needed to run the service reliably and prevent abuse.</li><li><strong>Product analytics and diagnostics.</strong> On the Langladder website and web app, PostHog collects a pseudonymous account identifier, basic browser and device information, coarse product actions (such as creating a deck or rating a review), technical error details, page URLs, referring pages, and marketing parameters used for traffic attribution. Account-recovery tokens, card-search terms, and tag names in URLs are masked. On the public homepage and non-authentication onboarding screens, PostHog also collects heatmaps and session recordings to help us improve those pages. Form inputs are masked, and recording is disabled on authentication and authenticated app pages.</li></ul><h2>How we use your information</h2><ul><li>To translate and define the pages and words you ask us to.</li><li>To store and schedule the vocabulary you save for review.</li><li>To authenticate you and keep you signed in across the web app and the browser extension.</li><li>To send transactional email such as address verification and password resets.</li><li>To understand whether core learning features are useful, improve the product, secure the service, prevent abuse, and fix problems.</li></ul><p>We do not sell your personal information, and we do not use your saved words or browsing to serve advertising.</p><h2>Service providers</h2><p>We rely on a small number of providers to operate Langladder, who handle data only to provide their service to us:</p><ul><li><strong>OpenRouter and AI model providers</strong> — generate translations and definitions from the text you submit. Our configured models include Google, OpenAI, and Anthropic;
1 hosting providers depend on OpenRouter routing. See <a href="https://openrouter.ai/privacy">OpenRouter’s privacy policy</a> <!-- -->and <a href="https://openrouter.ai/docs/guides/privacy/data-collection">data collection information</a>.</li><li><strong>Cloud infrastructure and email providers</strong> — hosting, database, and email delivery.</li><li><strong>Identity providers</strong> — only if you choose to sign in with a third-party account.</li><li><strong>PostHog</strong> — provides product analytics and browser error monitoring for the Langladder website and web app, and Simplify-click analytics for the Chrome extension.</li></ul><h2>The Chrome extension</h2><p>When you install the Chrome extension, it requires permission to read and change data on all websites. This access allows Langladder to read and update page text and, while translation is enabled, translate content automatically as you browse without requiring you to activate the extension on each page.</p><p>The Chrome extension only records a PostHog analytics event when you click Simplify. The event includes the selected target language and level, and your browser&#x27;s user-agent string, which identifies the browser and operating system and is sent with every web request. The event does not include the page you are on, your screen size, or your time zone.</p><p>The extension sends the text needed to provide the translation and learning features you use, including automatic translations, to our servers and AI providers as described above. If you choose to save a word or sentence, its source page URL is stored with that card in your account; this is part of the saved learning item, not analytics tracking. The extension does not request Chrome&#x27;s browsing history permission. It stores a session token locally so it can talk to your account; signing out of the extension clears it.</p><h2>The iOS app</h2><p>You can create an account and sign in by verifying an emailed code inside the app. Before your first rewrite, we ask permission to send visible page text (which may include personal or sensitive information), your target language, and reading level through Langladder to OpenRouter and its AI providers. While simplification is active, additional visible text is sent as you scroll or the page changes. Browsing remains available without this permission.</p><h2>Data retention &amp; your choices</h2><p>We keep your account and saved words until you delete them or close your account. You can delete saved cards from the web app at any time. In the iOS app, open Account → Delete account, verify an email code, and confirm permanent deletion. This removes your account, credentials, saved learning data, and review history and cancels your Langladder web subscription. Payment processors may retain transaction records required by law. Local tabs, website data, reading preferences, and AI permission are cleared on this device. To request a copy of your data or help with deletion, email us at the address below.</p><h2>Security</h2><p>Data is encrypted in transit, passwords are hashed, and every request is scoped to the signed-in account so your data is only ever accessible to you. No method of storage or transmission is perfectly secure, but we work to protect your information.</p><h2>Children</h2><p>Langladder is not directed to children under 13, and we do not knowingly collect personal information from them.</p><h2>Changes to this policy</h2><p>We may update this policy from time to time. When we do, we will revise the “Last updated” date above, and significant changes will be communicated where appropriate.</p><h2>Contact</h2><p>Questions about privacy? Email<!-- --> <a href="mailto:[email protected]">[email protected]</a>.</p></div></article></div></main><footer class="footer"><div class="container footer-inner"><a aria-label="Langladder home" href="/" class="logo"><span class="logo-mark"><span></span><span></span><span></span></span><span class="logo-word">Langladder</span></a><div class="footer-links"><a class="active" href="/privacy" data-status="active" aria-current="page">Privacy</a><a href="/terms">Terms</a><a href="mailto:[email protected]">Contact Us</a></div><div class="footer-copy">© 2026 Langladder</div></div></footer><!--/$-->
1<script class="$tsr" id="$tsr-stream-barrier">(self.$R=self.$R||{})["tsr"]=[];self.$_TSR={h(){this.hydrated=!0,this.c()},e(){this.streamEnded=!0,this.c()},c(){this.hydrated&&this.streamEnded&&(delete self.$_TSR,delete self.$R.tsr)},p(e){this.initialized?e():this.buffer.push(e)},buffer:[]};$_TSR.router=($R=>$R[0]={manifest:$R[1]={routes:$R[2]={__root__:$R[3]={preloads:$R[4]=["/assets/index-Dx81JACi.js"],assets:$R[5]=[$R[6]={tag:"script",attrs:$R[7]={type:"module",async:!0},children:"import(\"/assets/index-Dx81JACi.js\")"}]},"/privacy":$R[8]={preloads:$R[9]=["/assets/privacy-D7wBcKxu.js","/assets/legal-BIgB7SzV.js"]}}},matches:$R[10]=[$R[11]={i:"__root__�",u:1790904828161,s:"success",b:$R[12]={user:null},ssr:!0},$R[13]={i:"�privacy�privacy",u:1790904828161,s:"success",ssr:!0}],lastMatchId:"�privacy�privacy",dehydratedData:$R[14]={queryStream:$R[15]=($R[16]=(e) => new ReadableStream({ start: (r) => {
2	e.on({
3		next: (a) => {
4			try {
5				r.enqueue(a);
6			} catch (t) {}
7		},
8		throw: (a) => {
9			r.error(a);
10		},
11		return: () => {
12			try {
13				r.close();
14			} catch (a) {}
15		}
16	});
17} }))($R[17]=($R[18]=() => {
18	let e = [], r = [], t = !0, n = !1, a = 0, s = (l, g, S) => {
19		for (S = 0; S < a; S++) r[S] && r[S][g](l);
20	}, i = (l, g, S, d) => {
21		for (g = 0, S = e.length; g < S; g++) d = e[g], !t && g === S - 1 ? l[n ? "return" : "throw"](d) : l.next(d);
22	}, u = (l, g) => (t && (g = a++, r[g] = l), i(l), () => {
23		t && (r[g] = r[a], r[a--] = void 0);
24	});
25	return {
26		__SEROVAL_STREAM__: !0,
27		on: (l) => u(l),
28		next: (l) => {
29			t && (e.push(l), s(l, "next"));
30		},
31		throw: (l) => {
32			t && (e.push(l), s(l, "throw"), t = !1, n = !1, r.length = 0);
33		},
34		return: (l) => {
35			t && (e.push(l), s(l, "return"), t = !1, n = !0, r.length = 0);
36		}
37	};
38})()),dehydratedQueryClient:$R[19]={mutations:$R[20]=[],queries:$R[21]=[$R[22]={dehydratedAt:1790904828161,state:$R[23]={data:null,dataUpdateCount:1,dataUpdatedAt:1790904828161,error:null,errorUpdateCount:0,errorUpdatedAt:0,fetchFailureCount:0,fetchFailureReason:null,fetchMeta:null,isInvalidated:!1,status:"success",fetchStatus:"idle"},queryKey:$R[24]=["auth","user"],queryHash:"[\"auth\",\"user\"]"}]}}})($R["tsr"]);document.currentScript.remove()</script>
38<script type="module" async="">import("/assets/index-Dx81JACi.js")</script>
38<script>($R=>$R[17].return(void 0))($R["tsr"]);$_TSR.e();document.currentScript.remove()</script>
38</body></html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.