★ Pinboard Bookmark Enhanced

Privacy Policy: Pinboard Bookmark Enhanced

Last updated: 2026-10-04

Summary

Pinboard Bookmark Enhanced is local-first and bring-your-own-key. It has no developer servers, no analytics, no tracking, and no telemetry; the developer never receives your data. The extension uses Pinboard for its core bookmark features and contacts other services only as described below. Bookmark-status checks and offline-save retries can run automatically; separately enabled features such as Wayback archiving and key-points skim can also make automatic requests. After you have granted access to the online dictionary, opening a saved word on the Notes & Vocabulary page can also look it up automatically.

Google Drive sync remains off until you explicitly connect it on a device. Once connected, it syncs selected data for the current Pinboard account through the extension’s private Google Drive application-data folder. Vocabulary is selected by default; reader highlights and notes require a separate opt-in, off by default. The two data choices stay local to each device. Drive does not sync settings, credentials, unowned legacy highlights, or dictionary packs.

Data storage

Extension settings, caches, and temporary state are stored locally by default. Bookmarking and the configured features described under Network requests can transmit the specific data needed for those features. You can optionally enable settings sync (off by default); ordinary settings (not saved bookmarks or page content) are then synced across your devices through Chrome’s built-in account sync.

Data Default storage Synced via Google Account
Settings & preferences chrome.storage.local Only if you enable settings sync
Credentials and configured Webhook URLs (obfuscated) chrome.storage.local Only if you enable both settings sync and the separate API-key sync option
Custom CSS & themes chrome.storage.local Only if you enable settings sync; large synced values are chunked
AI result cache (account-scoped keys include the non-secret plaintext Pinboard username owner) IndexedDB No
Vocabulary book (account-scoped, includes the non-secret plaintext Pinboard username owner): saved words with their language, definition text, IPA, the sentence they appeared in, article URL/title, an optional note, and a highlight reference IndexedDB Only through the separately connected Google Drive feature described below
Drive sync runtime/account state: per-device connection marker, Drive account identity, changes cursors, notices, errors, and retry schedule chrome.storage.local and IndexedDB No
Pending vocabulary upload data: current outbox events and exact frozen immutable batch bodies; these local payloads contain the vocabulary and convergence fields listed in the next row IndexedDB Not through Chrome Sync; after connection, frozen batches are uploaded to Google Drive
Convergence metadata sent to Google Drive: owner hash, device identifier, record key, version vector, dot, and deletion marker; live events also contain the selected vocabulary or highlight-and-note fields described here Local vocabulary copies in IndexedDB; highlight-and-note copies in chrome.storage.local; no remote copy until connection, then Google Drive appDataFolder Only through the separately connected Google Drive feature for data types enabled on that device, never through Chrome Sync
CC-CEDICT offline dictionary pack (Chinese word, pinyin, and definition records from a file you import) IndexedDB (pbp-dict-packs) No
Offline English–Chinese dictionary pack in the ECDICT CSV field layout (headword, a lookup key derived from it, and Chinese definition text, all from a file you import), plus a record of how many entries were stored, when, the entry-selection level used, the decoded byte count, and a CRC32 checksum of those bytes for diagnostics IndexedDB (pbp-dict-packs) No
Tag cache & tag-cleanup state (account-scoped records include the non-secret plaintext Pinboard username owner) chrome.storage.local No
Video reading-view choice (per video: reading or timeline, with a last-used timestamp; account-scoped keys include the non-secret plaintext Pinboard username owner; at most 50 recent entries) chrome.storage.local No
Bookmark-status cache (account-scoped in memory) Service Worker memory No
Offline save queue (URL, title, notes, tags, save options, time, and a non-secret plaintext Pinboard username binding) chrome.storage.local No
Unsaved popup drafts (page/bookmark URLs, title, notes, tags and pending tag text, save options, and the non-secret Pinboard username owner; normal and incognito scopes are separate) chrome.storage.session; expire after 24 hours, with expired entries pruned on subsequent writes; cleared on browser restart, successful matching save, or logout No; excluded from manual backups
Batch progress & Markdown preview data (account-scoped records include the non-secret plaintext Pinboard username owner); for video pages this includes the captured subtitle text, the selected caption track, and AI punctuation results, so the reader can restore them after a reload without refetching chrome.storage.local No
Pending highlights-and-notes upload data: outbox events, immutable batch bodies, version vectors, and tombstones for the current Pinboard owner chrome.storage.local Only through Google Drive when highlights and notes are separately enabled on that device; never through Chrome Sync or manual backup
Reader highlights & notes: source URLs, titles, selected excerpts, note text, colors, and timestamps, scoped to a non-secret Pinboard owner chrome.storage.local Only through Google Drive when highlights and notes are separately enabled on that device; off by default
Wayback archive log chrome.storage.local No

Settings sync is implemented with Chrome’s chrome.storage.sync. Whether ordinary settings sync is enabled remains a per-device choice. The separate API-key-sync preference is an account-wide marker, but credentials are read from or written to Chrome Sync only on devices where ordinary settings sync is also enabled. New users start with credential sync off. During upgrade, if the account-wide marker is missing but Chrome Sync already contains a non-empty credential/export-target token, or the old device-local credential-sync preference was on, the marker is initialized on to preserve that existing opt-in and avoid credential loss; otherwise it is initialized off. API keys, tokens, passwords, configured Webhook URLs, and other export-target credentials stay local unless both settings sync and this account-wide credential option are enabled. These values are obfuscated at rest (not cryptographically encrypted). Public service requests use HTTPS; configured AI and Webhook endpoints may use plain HTTP only for the literal loopback hosts listed under Network requests. The extension has no developer server; automatic requests are limited to the core and enabled behaviors documented below.

While credential sync is enabled, each participating device also retains its last observed cloud credential snapshot locally. If another device turns credential sync off and removes the cloud copy, that local snapshot remains available. A device that was offline during a credential change can retain only the older snapshot it last received.

New offline-queue records never store a Pinboard API token. They store the bookmark fields listed above plus the Pinboard username parsed from the token as a non-secret account binding. Legacy queued records are rewritten to that format and their stored token field is removed. Retry always requires the currently configured token for the same username; logout or an account switch leaves the item queued and sends no request with an old credential.

To prevent one Pinboard account from seeing another account’s local state, account-derived records and caches carry the Pinboard username parsed from the token as a non-secret plaintext owner. This applies to the offline queue, tag caches and recent-tag state, Batch progress, tag-cleanup state, Markdown-preview handoffs, the vocabulary book, and other account-specific local state. Account-scoped AI cache keys (tags, summaries, translations, extracted translation glossaries, remembered translation views, and contextual dictionary glosses) include that username owner in the IndexedDB key. These owner bindings do not contain the API token and do not create an additional network request.

Manual backups are plaintext schema v3 JSON files you explicitly export. They contain settings and themes. You can separately include reader highlights and notes, which contain page URLs, page titles, selected text, note text, highlight colors, and timestamps. You can also include the current Pinboard account’s vocabulary records, including the vocabulary fields listed in the table above. OAuth data, Drive account data, version vectors, outbox, tombstones, and pending batches are never included.

Incognito windows. If you enable the extension for incognito windows in Chrome’s settings, it runs in Chrome’s default spanning mode: there is no separate incognito profile, so anything a save or preview persists (an offline-queue entry when you save while offline, a Markdown-preview handoff, reader highlights you create, AI caches) is written to the same on-device storage the regular windows use and remains there after the incognito window closes. Bookmarks saved from an incognito tab default to private on Pinboard, but that flag does not change what is stored locally. If you do not want incognito browsing reflected in on-device extension data, do not enable the extension for incognito windows. There is no single action that clears all of it afterwards: the options page’s Storage Management panel only reclaims a handful of chrome.storage.local caches (page extraction, bookmark URLs, tags, and AI-usage/compatibility memos); reader highlights and notes are managed from the Notes & Vocabulary page instead; the offline save queue can be emptied from the popup’s offline-queue bar (remove one entry or clear all) or drains itself once a queued bookmark is successfully replayed; and the AI result caches (tags, summaries, translations, and dictionary lookups) live in IndexedDB, bounded only by per-cache entry limits, with no manual clear control today.

Credentials are excluded unless you tick Include API keys and tokens in backups, which is off by default. With it ticked, the export writes your Pinboard token, every AI provider key, and the Jina, Wayback, AnkiConnect, Eudic, GitHub and Notion tokens and the Webhook authorization value or capability URL into the file in plain text, marks the file with credentials in its name, and records the fact in the file’s metadata. Such a file is equivalent to a password file: anyone who opens it can use those credentials. On import, credentials are a separate section that stays unticked even when the file contains them, so restoring settings never silently overwrites the keys already working on that device.

Chrome Web Store data categories

The Chrome Web Store privacy form uses standardized data categories. To keep the store listing consistent with this policy, this extension discloses that it handles the following categories:

Category Why it applies
Personally identifiable information Your Pinboard API token includes your Pinboard username; account-scoped local state and cache keys store that username owner in plaintext locally (without the token), including offline, tag, AI, Batch, tag-cleanup, and preview state
Authentication information The extension stores and uses credentials you provide, such as your Pinboard API token, AI/Jina provider keys, Wayback S3 credentials, GitHub token, webhook authorization value or capability URL, AnkiConnect API key, Eudic OpenAPI authorization value, and Notion internal integration token
Web history The extension reads page URLs and titles for bookmark status, popup prefill, batch save, Save Tab Set, offline queue, and bookmark/export metadata
Website content The extension can extract page text, selected text, links, metadata, highlights, and notes for AI tags/summaries, Markdown preview, Translate, Ask-the-page, Explain-selection, Dictionary lookups and the vocabulary book, exports, and manual settings-backup files

The extension does not collect health information, financial/payment information, location, personal communications as a separate category, or user activity for analytics/tracking. It has no developer-operated analytics, telemetry, advertising, or profiling.

Network requests

The extension uses the required Pinboard hosts for its core bookmark features. Configured AI, Jina, Wayback, Gist, Webhook, and Notion destinations, together with selected Batch source origins, require an optional grant for the exact current origin. The Google API grant for Google Drive sync follows the same direct-action rule described in item 16. Permission prompts are initiated only from a direct user action; automatic and background feature paths only check an existing grant and skip or fail safely when it is absent. Remote images retained in Markdown preview are normal browser subresource requests and do not use an extension host-permission grant; they are disclosed separately below.

  1. Pinboard API (api.pinboard.in): to save, retrieve, and manage your bookmarks, authenticated with your Pinboard API token. The tag-cleanup tool, when you run it, downloads your full bookmark/tag list (posts/all, tags/get) and re-saves affected bookmarks to rename or merge tags, all to and from your own Pinboard account. The extension also checks whether the current page is already bookmarked as you navigate, sending the active tab’s URL to the Pinboard API to set the toolbar icon state.

  2. Pinboard website (pinboard.in): (a) a content script applies your chosen theme CSS and tag-sort tweaks on pinboard.in pages; no data is extracted or transmitted. (b) Save Tab Set POSTs the open tabs’ titles and URLs to pinboard.in/tabs/save/ using your existing pinboard.in login session cookie (not the API token), then opens pinboard.in/tabs/show/ for you to confirm.

  3. AI provider APIs: the page title, URL, and extracted article text are sent to the provider you chose to generate AI tags, summaries, translations, Ask-the-page answers, selection explanations/translations, batch-save results, or AI punctuation for video subtitle transcripts (clicking the AI punctuation button on a video preview sends that video’s full transcript text to the provider across multiple batches). On a YouTube or bilibili video page, when the subtitle origin grant already stands and the option Use video captions as the AI content source is on (the default), the popup’s AI tags and summary send the video’s subtitle transcript in place of the page text, within the same size window; without that grant they use the page text as before. Tag/summary requests send roughly the first 8 KB of extracted text. AI-tag requests can also include up to 50 existing Pinboard tag names so the provider can prefer reuse. If you put `` in a custom tag or summary prompt, the current bookmark description or notes are included. Full-text Translate sends the translatable article across multiple batches; it is not reduced to one sampled context window. Translate does not create a summary, but when a summary for the same Pinboard account is already cached locally, that summary is included as context in each translation batch. The extension operates no translation snapshot or sharing service: translations stay on your device and with the AI provider you chose, unless you explicitly send them somewhere with a Send-to export action (items 6, 7, 8, 18, and 19). Ask-the-page and the opt-in key-points skim select article context within their token budgets. If you enable AI for Quick Save, Read Later, or Batch Save, the corresponding save action can initiate the configured AI work. If you separately opt in to key-points skim, opening Markdown preview can generate it automatically on a cache miss. Deep Analysis (AI) in tag governance sends tag names (and, when truncated, the number of omitted lower-frequency tags), not bookmark page content or per-tag use counts. Supported providers: OpenAI, Anthropic, Google Gemini, DeepSeek, Qwen, MiniMax, OpenRouter, Groq, Mistral, Cohere, SiliconFlow, Zhipu, Moonshot (Kimi), a local Ollama instance, or a Custom OpenAI-compatible endpoint. The first direct use requests only that provider’s exact origin; later automatic use proceeds only while that exact grant remains active. The Test Connection button next to each provider sends only a fixed one-line prompt (“Reply with just the word: OK”) to that provider, never page content or account data; when a Reader model override is set for the selected provider, the button sends that same prompt a second time using the override model.

  4. Jina Reader (r.jina.ai, optional): when you choose the Jina content source, the page URL is sent to Jina to fetch a cleaner reader-mode rendering for AI processing or Markdown export. If you configured a Jina API key, it is sent on a cache miss or refresh as a Bearer authorization value. Disabled by default. A cache hit stays local; a network cache miss requires an exact https://r.jina.ai grant.

  5. Wayback Machine (web.archive.org, optional, opt-in): when you enable Wayback archiving, the URL of a page you save can be submitted automatically to the Internet Archive to create a public snapshot. If you configured Wayback S3 access credentials, the access key and secret are sent in the request’s authorization header. It is off by default and requires an exact https://web.archive.org grant. Background saves only check that grant; if it is absent, the archive is not submitted and the permission-required outcome is logged locally.

  6. Obsidian (local app, optional): the Send to Obsidian action hands the converted Markdown of the current page to your local Obsidian desktop app via the obsidian:// protocol or the system clipboard. This stays on your device; nothing is sent over the network.

  7. GitHub Gist (api.github.com, optional; inactive until you configure it): the Send to Gist action uploads the converted Markdown of the current page (including its metadata frontmatter) as a secret gist on your own GitHub account, authenticated with a personal access token you provide. The action requests only the exact https://api.github.com origin.

  8. Webhook (a URL you configure, optional; inactive until you configure it): the Send to Webhook action POSTs a JSON payload to the endpoint you entered (e.g. Readwise), with an Authorization header value you provide. The payload contains the page’s title, URL, save date, tags, and converted Markdown; when extended export metadata is enabled (default on), it also includes the page’s author, original publish date, site name, cover-image URL, and word count. The action requests only that endpoint’s exact origin. An unsafe endpoint is blocked rather than warned-and-sent.

  9. Selected Batch Save sites (local extraction access, not a data destination): when AI is enabled for Batch Save, Chrome asks for the exact origins of the selected HTTP/S tabs so the extension can extract their page text locally, together with the exact current AI-provider origin. The confirmation view lists every requested origin. The extension does not request the all-sites wildcard at runtime; extracted content is sent only to the selected AI provider as described above.

  10. Remote image hosts in Markdown preview: sanitized Markdown can retain remote image URLs. When the preview renders those images, the browser requests them directly from the original site or image/CDN host without a separate extension host-permission prompt. Every retained image is forced to referrerpolicy="no-referrer", so the referring article/preview URL is not sent in the Referer header. The image host still receives the requested image URL and ordinary connection/request metadata such as the user’s IP address and browser headers; cookies are included only when permitted by Chrome’s cookie and third-party-cookie policies.

  11. Embed (offline) image export in Markdown preview (image hosts referenced by the exported document, optional): this is a separate mechanism from the ordinary <img> rendering described above. Choosing the Embed (offline) image policy for a Markdown/HTML/EPUB download makes the extension page itself fetch each remote image directly from its own host (credentials: "omit") and convert it to a data URI (or, for EPUB, bundle it as a file inside the book) so the downloaded file renders offline. This only runs when you click Download with that policy selected, and requires a one-time optional host-permission grant for the exact image origins found in the document; declining leaves those images as ordinary remote links in the export instead of embedding them. Images that fail this plain fetch (typically hosts that reject requests without a Referer header) are retried once behind the temporary Referer rule described in item 12, within the same download-size budget. No image data passes through any intermediary.

  12. Fix images blocked by hotlink protection in Markdown preview (image hosts, optional): some sites reject any image request that carries no Referer header, and an extension page can only send referrerless requests, so those images fail to load in the preview. When that happens, the preview shows a count and a Fix button. Clicking it asks for a one-time optional host-permission grant for the exact failed image origins, then re-fetches only those images (credentials: "omit") while a temporary declarativeNetRequest session rule (scoped to those image domains, to the fetch request type, and to that one preview tab) sets the Referer header to the article page’s origin (never the full article URL or its query). The rule is removed as soon as the fetch run finishes, and fixed images are displayed as inline data URIs for that page view only; nothing is written to storage. For image origins you have already granted, later previews re-apply this fix automatically; the automatic path only checks the existing grant (permissions.contains) and never prompts. Declining the permission leaves the images as broken placeholders.

  13. Free Dictionary API (freedictionaryapi.com, optional): when you use the Dictionary lookup in Markdown preview and grant an exact https://freedictionaryapi.com origin, the selected word and its language code are sent to fetch Wiktionary-based definitions. The same lookup can also be started from the Notes & Vocabulary page: clicking the dictionary lookup button on a saved word (including Look up again), submitting the page’s own lookup box (an empty box looks up the open word), or changing the dictionary language after a lookup has run. After you have granted access to the online dictionary, opening a saved word on that page also looks it up automatically when no installed offline dictionary has an entry for it. Each of these sends that word and its language code to the same endpoint; a result already cached on your device is reused without a request. Opening the page itself sends nothing, and the lookup never runs in the background.

  14. AnkiConnect (http://127.0.0.1:<port>, local loopback, port configurable in settings with 8765 as the default, optional; inactive until you click Send all to Anki or Test AnkiConnect): the Send all to Anki action sends every vocabulary book entry belonging to the current Pinboard account, including its term, reading, definition, contexts, source, and license text, to a locally running Anki instance through the AnkiConnect add-on. It uses an API key you provide if AnkiConnect requires one. The request always targets the loopback address 127.0.0.1 (only the port is configurable); it never reaches the public internet or the developer. The action requests only that exact origin and runs only when you click Send all to Anki. The Test AnkiConnect button in settings performs the same handshake against the same loopback origin (plus a version call carrying your API key when AnkiConnect requires one) and sends no vocabulary data.

  15. Eudic OpenAPI (api.frdic.com, optional; inactive until you click Send all supported words to Eudic or Test Eudic connection): the Send all supported words to Eudic action checks every vocabulary book entry belonging to the current Pinboard account. It sends the term text and language code of entries in a supported language (English, French, German, or Spanish) to your Eudic account’s default study list for that language, authenticated with an OpenAPI authorization value you provide. Entries in unsupported languages are skipped and not sent. The action requests only that exact origin and runs only when you click Send all supported words to Eudic. The Test Eudic connection button in settings sends a single read-only study-list category request to the same origin, carrying only your authorization value and no vocabulary data.

  16. Google Drive API (www.googleapis.com, optional): clicking Connect Google Drive is the only action that can request the optional Chrome identity permission and exact https://www.googleapis.com origin. The extension uses the drive.appdata scope to store immutable batches for the data types selected on that device in its private appDataFolder, not in your visible Drive files. Vocabulary batches contain plaintext words, definitions, IPA, groups, notes, source URLs, article titles, context excerpts, source-license data, and timestamps. When separately enabled on that device, highlights-and-notes batches contain the current Pinboard owner’s highlighted excerpts, notes, source URLs and titles, colors, timestamps, and anchor information. That data type is off by default; Drive sync does not upload or claim unowned legacy records. Both batch types also contain an owner hash, a device identifier, record keys, version vectors, dots, and deletion markers used for convergence; the plaintext Pinboard username and all credentials are excluded. The extension calls Drive about.get to identify the connected account and stores its permission ID, email address, and display name locally with cursors, pending work, errors, and retry state. After a device is connected, pending local changes can schedule a sync after 30 seconds and a periodic check can run every 15 minutes. These automatic runs only check existing permissions and never open an OAuth prompt. Disconnect this device removes the cached OAuth token and optional grants but does not delete local vocabulary, highlights or notes, local convergence state, or remote appDataFolder batches.

  17. Browser speech synthesis for pronunciation (no extension permission involved): the pronunciation button in the Dictionary lookup uses the browser’s built-in Web Speech API. The extension prefers a voice the browser reports as running on your device, so in the common case the word never leaves your computer. Some voices are network-backed instead; on desktop Chrome these are the built-in “Google language” voices, which synthesize speech on Google’s servers. If your browser offers no on-device voice for the detected language, or no language was detected, the browser can fall back to one of those network voices, and the text being spoken (the selected word or phrase, truncated to 200 characters, never the article) is sent to that speech service by Chrome itself. This path uses no extension host permission, so there is no permission prompt to accept or decline; which voices exist and which is used by default are controlled by your operating system and your Chrome settings.

  18. Notion (api.notion.com, optional; inactive until you configure it): the Send to Notion action creates a new page under a parent page you choose in your own Notion workspace, authenticated with an internal integration token you provide. The request carries the page’s title, source URL, tags, and converted Markdown as the new page’s content. The action requests only the exact https://api.notion.com origin.

  19. NotebookLM (no network access; optional): the Send to NotebookLM action copies the converted Markdown to your system clipboard and opens notebooklm.google.com in a new tab. The extension itself sends nothing over the network and requests no host permission for it; the content reaches Google only if you paste it there yourself.

  20. YouTube video and subtitles in Markdown preview (www.youtube.com, optional; only for previews of YouTube video pages): opening the preview of a YouTube video page automatically requests a poster thumbnail from https://i.ytimg.com/vi/<id>/hqdefault.jpg for the entry card; this is an ordinary <img> request with referrerpolicy="no-referrer" set, and, as with other retained preview images (item 10), cookies are included only when Chrome’s cookie and third-party-cookie policies would otherwise send them to that host. The first time you use this on a video page, an Enable subtitles & load video button asks once for the exact https://www.youtube.com origin; no watch-page, subtitle, or player request is made before that click (the poster thumbnail described above is the only request that precedes it). Once that grant stands, opening the preview of a YouTube video page runs the caption capture automatically (the extension only checks the existing grant, it never re-prompts), because the transcript now IS the page’s article rather than an optional panel. With that grant, if a www.youtube.com tab is open in your browser (preferring the tab this preview came from), the video’s ordinary watch page and the selected subtitle track are read inside that tab, with the tab’s own session: the same requests that page could make itself, sending nothing beyond what your own YouTube session already sends. When that direct route is withheld, the extension may instead drive that tab’s own player to load the captions, or open and read YouTube’s own transcript panel in that tab; both act only within that tab and send nothing beyond what the page itself would. When no YouTube tab is open, the extension falls back to requesting the same watch page and track text directly from the reader page; only this fallback is governed by Send YouTube login cookies with subtitle requests (on by default, because an anonymous fallback request is more likely to be treated as automated traffic and refused outright; turning it off makes the fallback cookieless, credentials: "omit", at the cost of finding subtitles less often). YouTube restricts caption access for some videos, and those simply report no subtitles. Clicking the entry card also loads the player, embedded through a small page published on this project’s own GitHub Pages site (pine2d.github.io), which exists only because Chrome sends no Referer from extension frames and YouTube’s player refuses to load without one; that relay page builds the player through YouTube’s own IFrame API, loading YouTube’s official player script (iframe_api, which loads www-widgetapi.js in turn) only on the Pages origin and never inside the extension. It forwards play and seek commands from the reader, reads back the player’s public playback position and state through that same official API, and reports them only to the reader page that first messaged it, an origin captured from and checked against that first message; it stores nothing. It uses the ordinary YouTube domain rather than the privacy-enhanced youtube-nocookie.com one because the latter is a separate domain that your login cookies never reach, which made YouTube treat the embedded player as automated traffic and refuse to play. The tradeoff is the cookies the ordinary domain sets, the same ones any YouTube embed on any website sets. Loading the relay needs no host-permission grant, since it is a frame rather than a fetch, so the player still loads even if you decline the subtitle-origin prompt. An always-present open on YouTube link next to the player opens the ordinary youtube.com/watch page in a new tab, as a fallback for when the relay cannot load. With the grant standing, opening such a preview also loads the embedded player automatically. Nothing is sent for non-YouTube pages, and revoking the origin in Chrome’s site settings returns the page to the ask-first state. The popup’s AI tags and summary reuse this same standing grant to read the subtitles as their content (see item 3): they only ever check that the grant exists and never prompt for it.

  21. Bilibili subtitles in Markdown preview (api.bilibili.com, optional; only for previews of bilibili video pages): the first Enable subtitles & load video click asks once for the exact https://api.bilibili.com origin; once that grant stands, opening the preview of a bilibili video page automatically calls bilibili’s view, nav, and WBI-signed player endpoints to list and fetch subtitle tracks. Because bilibili only returns subtitles to a logged-in account, these three requests are sent with your bilibili login cookies (credentials: "include", first-party to bilibili’s own API, the same session your browser already holds); the subtitle text file itself is fetched from bilibili’s CDN without cookies. Signed in, this reads your session’s subtitle access; signed out, bilibili returns an empty list and the panel shows a sign-in hint. The embedded player loads from player.bilibili.com inside a frame, automatically once the grant stands (the transcript is the page’s article). The same click also asks for the exact https://player.bilibili.com origin: with it, the extension registers a small script that runs only inside player.bilibili.com frames and stays inert until a preview page of this extension greets it; it then reports the player’s current time, play/pause state and duration to that preview page (and nowhere else – every message is addressed to this extension’s own origin) and accepts seek / play / pause / speed commands from it, so the transcript can follow playback the way it does for YouTube. It reads nothing else from the player page and sends nothing to bilibili. Nothing is sent for non-bilibili pages, and revoking either origin returns the page to the ask-first state (without the player origin, the transcript falls back to jump-on-click only). The popup’s AI tags and summary reuse this same standing grant to read the subtitles as their content (see item 3): they only ever check that the grant exists and never prompt for it.

For configured AI and Webhook destinations, HTTPS is required. Plain HTTP is accepted only for the literal loopback hosts localhost, 127.0.0.1, and [::1] (with an optional port). Public or LAN HTTP hosts, alternate loopback spellings, wildcard hosts, and URLs containing embedded credentials are blocked before any request. The configuration is retained so you can correct it; permission denial or revocation likewise preserves keys and settings.

Page content, URLs, credentials, and remote-image requests are transmitted only as described above, and never to the developer.

Permissions

Permission Purpose
activeTab Read the current page’s title, URL, and selected text for bookmarking and content extraction
storage Store settings, obfuscated keys, queues, and caches; ordinary settings sync per enabled device, and credentials sync on participating devices only with the separate account-wide API-key sync option
scripting Inject the Defuddle extractor (and optional per-site rules) into the active tab to pull clean article text, only on explicit action: AI tags/summary, Markdown preview / Translate / Ask / Explain, or batch-save with AI. Two further uses, both behind the exact-origin grants described in items 20 and 21: on a YouTube-page preview, read the caption text through an open www.youtube.com tab of that video (a same-origin fetch, driving that tab’s own player to load the captions, or reading YouTube’s own transcript panel there) when the direct caption route is withheld; and, once player.bilibili.com is granted, register a small content script for that origin’s player frames so the preview can follow playback (inert until the preview page greets it; see item 21). A third use, also behind an exact-origin grant: when a page keeps its article inside one large embedded frame from another site (an app shell such as a claude.ai artifact) and the top document yields nothing, the preview offers Grant access and retry for that frame’s origin (a suggestion read from the frame’s src, confirmed in Chrome’s own prompt); only after you grant it does the extractor run again, and then only inside frames that really belong to that origin (checked against the live grant and each frame’s own origin), for that preview
tabs Read tab URLs/titles for bookmark-status detection, batch save, and Save Tab Set
notifications Show save confirmations and a 30-second Undo button
alarms Keep the Service Worker warm, retry the offline save queue, refresh the unread badge, prime storage defaults, and optionally prewarm Pinboard tags
identity (optional) Obtain and revoke the Google OAuth token for Google Drive sync only after you click Connect Google Drive; the extension does not request identity.email
declarativeNetRequestWithHostAccess Set the Referer header (to the article page’s origin) on the extension’s own image re-fetches during the preview’s Fix-images action and the Embed-export retry. Only effective for image origins you granted, only for requests from that preview tab, via a temporary session rule removed after each run; it grants no page access by itself and never touches other tabs’ or sites’ traffic
host_permissions Required access only to api.pinboard.in and pinboard.in for core bookmark API and website features
optional_host_permissions: https://*/* plus literal-loopback HTTP (localhost / 127.0.0.1 / [::1]) (declaration ceiling) Allows Chrome to offer exact runtime grants for user-selected origins: HTTPS anywhere, HTTP only on the local machine. The extension requests only the current AI/Jina/Wayback/Gist/Webhook/Notion origin, the selected Batch tab origins, the exact origins of the images referenced in a Markdown/HTML/EPUB export when you download it with the Embed (offline) image policy, the exact origins of the failed images when you click Fix on the preview’s blocked-images notice, the exact https://freedictionaryapi.com origin requested the first time you use the Dictionary lookup in Markdown preview, or the first time you click the dictionary lookup button on a saved word or use the page’s own lookup box on the Notes & Vocabulary page (opening a saved word never asks for this grant), the exact http://127.0.0.1:<port> AnkiConnect loopback origin (port from your settings, default 8765) requested when you click Send all to Anki or Test AnkiConnect, the exact https://api.frdic.com Eudic origin requested the first time you click Send all supported words to Eudic or Test Eudic connection, the exact https://www.googleapis.com Google Drive origin requested when you click Connect Google Drive, the origin of a page’s dominant visible embedded frame requested when you click Grant access and retry on a Markdown preview whose article may live inside that cross-origin frame (the suggested origin is read from the frame’s src and confirmed in Chrome’s prompt; the extractor then runs only in frames that really belong to it; nothing is requested for hidden frames, srcdoc frames or frames sandboxed without allow-same-origin; declining simply leaves the “no content” notice; like every other grant here it stays until you revoke it in Chrome’s site settings), the exact www.youtube.com origin requested when you click Load video & subtitles on a YouTube-page preview, or the exact api.bilibili.com and player.bilibili.com origins requested together when you click Load video & subtitles on a bilibili-page preview (the second one powers the playback-sync bridge described in item 21; readers who granted before it existed get an Enable playback sync button that asks for it alone) (each a one-time prompt that can be declined; declining the Dictionary lookup grant only disables the Wiktionary lookup, and the AI explanation (if configured) and pronunciation still work; declining the AnkiConnect grant only disables Send all to Anki, and TSV export still works; declining the Eudic grant only disables Send all supported words to Eudic, and TSV export still works; declining the Google Drive grant leaves Google Drive sync disconnected without changing local vocabulary, highlights, notes, or manual exports; declining the YouTube grant leaves the subtitles unavailable for that preview, while the embedded player itself still loads; declining the Bilibili grant leaves the subtitles unavailable for that preview, while the embedded player itself still loads; the two bilibili origins are asked for together, so declining leaves subtitles unavailable for that preview while the player still loads; revoking player.bilibili.com afterwards in Chrome’s site settings keeps subtitles working and leaves the transcript on jump-on-click without follow). The extension never requests these ceiling patterns themselves

Optional grants are requested from a direct user action and remain under Chrome’s permission controls. Automatic feature paths that require an optional grant use permissions.contains only and never prompt. On upgrade from a legacy version that may have retained an all-sites grant, the extension performs a one-time removal of that wildcard grant. This can also clear matching old exact grants, but configurations are preserved and the next direct use can restore only the exact origin needed. On Chrome 142 and later, granting the AnkiConnect loopback origin can also trigger a separate Local Network Access (LNA) prompt from Chrome itself before the request reaches 127.0.0.1; declining that prompt leaves Send all to Anki unavailable without affecting any other permission.

Third-party services

The extension communicates with the following services or destinations for the corresponding behavior:

Optional-service permission denial or revocation sends nothing to that destination and does not erase its configuration. Selected Batch sites are accessed only to extract the content requested for that batch; they do not receive data from the extension.

Other than the services, configured destinations, Chrome Sync, and remote image hosts described above, the extension does not intentionally send data to third parties. No data is sent to the developer.

Changes

If this privacy policy changes, the update will be included in the extension release notes and the Last updated date above will be revised.

Contact

For questions about this privacy policy, open an issue at: https://github.com/pine2D/Pinboard-Bookmark-Enhanced/issues