Browser Sync

by Aki Hakune
5
4
3
2
1
Score: 50/100

Description

Sync all your browsers' history to Obsidian as plain Markdown

Reviews

No reviews yet.

Stats

0
stars
30
downloads
0
forks
14
days
6
days
6
days
0
total PRs
0
open PRs
0
closed PRs
0
merged PRs
0
total issues
0
open issues
0
closed issues
42
commits

Latest Version

7 days ago

Changelog

Add support for further export formats than Markdown.

README file from

Github

Obsidian Browser Sync

Obsidian Browser Sync is a desktop-only Obsidian plugin that imports local browser visits into Markdown, CSV, or JSON files. It preserves every visit, including repeated visits to the same URL, and imports every detected profile for each enabled browser.

Imports run only when you choose Import browser history from Obsidian's command palette. The plugin has no startup import, timer, background watcher, ribbon action, or mobile support.

Requirements and browser support

  • Obsidian desktop 1.13.0 or later on macOS, Windows, or Linux.
  • A locally installed, supported browser with persisted history. Private or incognito visits that the browser does not save cannot be imported.
Browser macOS Windows Linux
Safari First-class support Not available Not available
Firefox First-class support First-class support First-class support
Google Chrome First-class support First-class support First-class support
Microsoft Edge Compatible Chromium adapter Compatible Chromium adapter Compatible Chromium adapter
Brave Compatible Chromium adapter Compatible Chromium adapter Compatible Chromium adapter
Chromium Compatible Chromium adapter Compatible Chromium adapter Compatible Chromium adapter
Vivaldi Compatible Chromium adapter Compatible Chromium adapter Compatible Chromium adapter

Compatible Chromium browsers are read when their local history schema matches Chrome's. Browser schema changes may require a plugin update. A missing browser is skipped, and a failure in one profile does not stop healthy profiles from importing.

Install

From Community Plugins

When the plugin is available in the Obsidian Community Plugins catalog, search for Browser Sync, install it, and enable it. The stable Community plugin ID is browser-history-sync.

From a release

  1. Create <vault>/.obsidian/plugins/browser-history-sync/.
  2. Copy main.js, manifest.json, and styles.css into that directory. No other runtime file is required.
  3. Restart Obsidian, or reload the app without saving.
  4. Open Settings → Community plugins and enable Browser Sync.

From source

Install a current Node.js release supported by the repository's dependencies, then run:

npm ci
npm test
npm run build
npm run test:release

npm test is artifact-independent and succeeds before a build. npm run build writes the complete three-file plugin to build/, and npm run test:release stages that output in an isolated temporary directory for verification. Copy build/main.js, build/manifest.json, and build/styles.css into <vault>/.obsidian/plugins/browser-history-sync/. Development dependencies remain in the source checkout; they are not part of the installed plugin. The production sql.js WebAssembly bytes are embedded in generated build/main.js at build time.

Use

  1. Open Settings → Browser Sync and review the browser sources, output folder, export format, layout, and note period.
  2. Open the command palette and run Import browser history.
  3. Run the same command whenever you want to import newer visits.
  4. If generated notes were partially deleted or you want to backfill a different existing output folder, run Rebuild browser history output.

The plugin discovers all profiles for every enabled browser and writes a separate entry for each visit. Two visits to the same URL remain two entries. Very recent visits still present only in a browser's uncheckpointed write-ahead log may appear on a later run.

Settings and paths

The settings page provides:

  • A toggle for Safari, Firefox, Google Chrome, Microsoft Edge, Brave, Chromium, and Vivaldi. Sources default to enabled; unavailable or undetected sources are skipped.
  • A vault-relative output folder with suggestions from existing vault folders. The default is Browser History. Absolute and drive-relative paths, parent traversal, .obsidian aliases, Windows reserved names/characters, and components with trailing dots or spaces are rejected on every platform.
  • A file name template containing {period}. The default is {period}; for example, Browser history - {period} produces Browser history - 2026-08.md, .csv, or .json for a monthly export. The selected format's extension is added automatically, and folders or unknown placeholders are rejected.
  • An Export format dropdown with Markdown, CSV, and JSON. The default is Markdown. Changing it affects future imports; it does not rename or rewrite existing exports.
  • A Format conversion behavior dropdown with Keep original files and Replace original files. The default is Keep original files, and the choice applies only when the conversion command runs.
  • A Flat or Tiered layout. The default is Tiered.
  • A Day, ISO week, Month, or Year note period. The default is Month.
  • A read-only list of detected profiles and their availability or permission status.

With the defaults, an August 2026 visit is written to:

Browser History/2026/2026-08.md

For a monthly period, each format uses the same period path and its own extension:

Layout Markdown CSV JSON
Flat History/2026-08.md History/2026-08.csv History/2026-08.json
Tiered History/2026/2026-08.md History/2026/2026-08.csv History/2026/2026-08.json

Flat layouts place exports directly in the output folder. These Markdown examples show each period:

History/2026-08-03.md
History/2026-W32.md
History/2026-08.md
History/2026.md

Tiered layouts create time folders down to the selected period. The same paths end in .csv or .json when that export format is selected:

History/2026.md
History/2026/2026-08.md
History/2026/2026-08/2026-W32.md
History/2026/2026-08/2026-W32/2026-08-03.md

Week grouping follows ISO 8601: weeks begin on Monday and use the ISO week-year. For tiered week and day layouts, the parent year and month come from that week's Monday so an entire week stays together across a month or year boundary. For example, Thursday 2026-01-01 belongs to ISO week 2026-W01, whose Monday is 2025-12-29:

History/2025/2025-12/2026-W01.md
History/2025/2025-12/2026-W01/2026-01-01.md

Dates, times, and filenames use the local timezone of the Obsidian desktop environment at import time. Every visit has a full local ISO timestamp such as 2026-08-03T09:14:32+03:00, including the applicable UTC offset. Existing Markdown notes keep user-authored content; the plugin appends entries and never reformats or deletes that content.

Export formats

All formats represent the same canonical visit records. Modern records include sync metadata (namespace, browser ID, and deterministic visit ID), while the field remains optional so legacy records without it stay supported. Markdown is human-readable and uses hidden comments for sync metadata. Only HTTP(S) URLs are rendered as links; non-web schemes and malformed URLs remain inert text.

JSON exports use schema_version: 1, type: "browser_history", document metadata, and a records array. CSV exports use RFC 4180 quoting and this fixed header:

schema_version,type,metadata_browser_sync,metadata_period,metadata_heading,metadata_source_format,timestamp,title,url,browser,profile,representation,original_title,sync_namespace,sync_browser,sync_id

CSV cells beginning with =, +, -, @, a tab, or a line break are encoded so spreadsheet applications do not interpret imported history text as formulas. The encoding is reversible when Browser Sync reads the CSV again.

Converting existing exports

After selecting the desired Export format, run Convert existing browser history exports from the command palette. The command scans managed .md, .csv, and .json files in the configured output folder, reconciles records by period, and writes the selected format using the current file name template and layout. It ignores unmanaged files and does not alter browser cursor state.

With Keep original files (the default), successful conversion leaves source files in place. With Replace original files, a source is moved to Obsidian's recoverable system trash only after the destination has been written, parsed, and read back successfully. A source is retained after any failure or concurrent change. Markdown containing user-authored or otherwise unrecognized content is also retained, even when replacement is selected, so conversion never discards that content. Existing unmanaged destination files are not overwritten.

Changing Export format preserves the profile cursors already stored in data.json, so the next normal import writes only visits newer than those cursors to the newly selected format. Run the conversion command if historical output should also exist in the new format.

Idempotency and state

Each modern imported record has an obsidian-browser-sync namespace and a deterministic, path-independent visit ID. Markdown stores it in a hidden marker, while CSV and JSON store it in explicit sync fields. The namespace is retained for compatibility even though the Community plugin ID is browser-history-sync. The plugin indexes sync IDs vault-wide across Markdown, CSV, and JSON before importing, so those IDs remain the final deduplication authority after a change to the output format, folder, layout, period, timezone, or local browser-profile path. Running the command twice without new history adds nothing. Normal imports do not move or rewrite existing Markdown notes or user-authored content.

The plugin also saves a timestamp and source-visit-ID high-water cursor for each local browser profile in version 3 of its data.json. Cursor state is device-specific and should not be treated as portable vault content. A random per-device token is stored outside the synced vault in Obsidian/Electron local storage; only its SHA-256 hash is written to data.json.

If state is deleted or omitted from Git, the local device token is cleared, or the saved hash does not match, the next import invalidates cursors and rescans from the beginning. Copying data.json to another device is rejected even when both devices report identical platform, hostname, home-directory, and browser paths. Existing sync IDs remain device-independent and prevent duplicate modern records. Legacy records without sync IDs cannot be indexed, so they can be imported again after device-state invalidation if the browser still retains those visits. Keep hidden sync markers in generated Markdown if you edit it.

Each import uses an immutable snapshot of the settings that were active when the command was invoked. Settings changed while an import is running apply only to the next run.

If the active output folder is missing, a normal import automatically clears the local browser cursors and rebuilds that folder from all history still available in the enabled browsers. The rebuild scans hidden markers only inside the active output folder, so an obsolete copy elsewhere in the vault does not block restoration. If the folder still exists but some notes are missing, or a newly selected destination already exists, use Rebuild browser history output to trigger the same recovery explicitly. Surviving marked entries in the active folder are retained without duplication.

Safari permission and retry guidance

macOS may block access to Safari history until Obsidian has Full Disk Access:

  1. Quit Obsidian.
  2. Open System Settings → Privacy & Security → Full Disk Access.
  3. Add Obsidian if necessary and enable its switch.
  4. Reopen Obsidian and run Import browser history again.

The plugin reads a temporary snapshot rather than opening the live browser database for writing. If a profile still reports a database lock, copy error, or incomplete latest history, close that browser completely and retry the command. Retrying is safe: written markers prevent duplicates, and a failed note write does not advance that profile's cursor.

Privacy

All processing and format conversion stay on the local machine. The plugin makes no network requests, opens browser databases read-only, never writes to or deletes browser data, and removes temporary database snapshots after each profile attempt. A cleanup failure is reported explicitly because a sensitive temporary snapshot may remain. The plugin writes generated exports under the configured vault folder, settings and a device-identity hash in its data.json, and the raw random device token only in local application storage outside the vault.

Browser titles, URLs, browser names, and profile labels are treated as untrusted text. Markdown escapes them before rendering, and CSV applies reversible spreadsheet-safety encoding. Only http: and https: destinations become Markdown links; other schemes and malformed URLs remain inert text. Corrupt, negative, unrepresentable, or implausibly future timestamps are skipped at the profile-reader boundary. Visits not persisted by a browser, such as most private or incognito activity, are unavailable to the plugin.

Git-controlled vaults

The release has no separate WASM sidecar: the production sql.js WebAssembly bytes are embedded in .obsidian/plugins/browser-history-sync/main.js. For a Git-controlled vault, either ignore the installed plugin directory or intentionally version the three Community release files. Generated browser history uses ordinary Markdown, CSV, or JSON and can be reviewed, diffed, and versioned normally. Consider excluding the plugin's device-specific data.json while retaining sync metadata in history exports.

Development verification

npm run lint
npm test
npm run build
npm run test:release

Run the commands in that order: the default suite is intentionally independent of ignored build artifacts, while release verification requires a fresh build/ directory. Tests use synthetic database fixtures and in-memory vaults. They never inspect real browser history.