Back to Blog
Identity

Browser Bookmark Injection: Pre-Populate Bookmarks Automatically

How to pre-populate browser bookmarks programmatically for complete, realistic browser identities in automated workflows.

Introduction

A real browser carries history. It has bookmarks saved over weeks and months, organized into folders, reflecting the user's interests and habits. When you launch a fresh browser instance for automation or privacy research, the empty bookmark bar is one of many signals that distinguish it from a browser with genuine usage history. Bookmarks are part of the broader identity layer that makes a browser session look lived-in rather than freshly created.

BotBrowser provides the --bot-bookmarks flag to pre-populate the bookmark bar when launching a browser instance. This allows you to create sessions that include realistic bookmark data from the very first page load. Combined with other identity flags like --bot-cookies and --bot-inject-random-history, bookmarks contribute to a complete browser identity that is consistent across all layers.

Privacy Impact: Why Bookmarks Matter

Tracking systems collect many signals to build a profile of the browser they are interacting with. While cookies and fingerprints are the most commonly discussed, behavioral and state signals also play a role. The presence or absence of bookmarks, the number of entries in browsing history, and the state of the bookmark bar all contribute to the overall picture of a browser session.

For privacy researchers, controlling bookmark state is important for reproducible experiments. If you are testing whether a tracking system behaves differently for new versus returning visitors, you need to control every aspect of the browser's state, including bookmarks. For multi-account management, each identity benefits from a unique set of bookmarks that aligns with the rest of its profile: a German-language profile should have German bookmarks, a developer profile should have technical bookmarks, and so on.

Empty bookmark bars are also a practical problem. Some workflows require interacting with bookmark-related UI elements or testing how websites respond to the chrome.bookmarks API. Pre-populating bookmarks provides a realistic starting point for these scenarios.

Technical Background

How Chromium Stores Bookmarks

Chromium stores bookmarks in a JSON file called Bookmarks within the user data directory, specifically under the profile folder (e.g., Default/Bookmarks). This file contains a tree structure with two root nodes: bookmark_bar (visible on the bookmark bar) and other (the "Other Bookmarks" folder).

Each bookmark entry has these properties:

  • name/title: The display text shown in the bookmark bar or manager
  • url: The target URL for URL-type bookmarks
  • type: Either url for a bookmark or folder for a folder containing children
  • children: An array of nested bookmarks and folders (for folder-type entries)
  • date_added: A timestamp representing when the bookmark was created

When the browser launches, it reads this file and populates the bookmark bar and bookmark manager. Extensions and JavaScript running in privileged contexts can query bookmarks through the chrome.bookmarks API.

Bookmark Visibility

Bookmarks appear in several places within the browser:

  1. Bookmark bar: The most visible location, shown below the address bar when enabled
  2. Bookmark manager: Accessible through chrome://bookmarks
  3. New Tab page: Some configurations show frequently bookmarked sites
  4. Omnibox suggestions: The address bar may suggest bookmarked URLs as you type

Pre-populating bookmarks through --bot-bookmarks ensures they appear in all of these locations consistently.

Common Approaches and Their Limitations

Manually Editing the Bookmarks File

You can create a user data directory, manually create or edit the Bookmarks JSON file, and then launch the browser with that directory. This works but has several drawbacks:

  • The Bookmarks file format includes metadata fields (GUIDs, date_added timestamps in Chromium's internal format) that must be correct
  • You need to manage user data directories explicitly, tracking which directory belongs to which identity
  • There is no clean separation between bookmark data and other persisted state in the directory

Using the chrome.bookmarks API

The chrome.bookmarks API allows creating bookmarks programmatically, but it is only available to browser extensions, not to regular page JavaScript or automation frameworks. This means you would need to install an extension to manage bookmarks, which adds complexity and introduces a detectable signal (the extension itself).

Framework-Level Approaches

Neither Playwright nor Puppeteer provides a native bookmarks API. The only built-in way to manage bookmarks through these frameworks is by navigating to chrome://bookmarks and interacting with the UI, which is slow and fragile.

BotBrowser's Approach

BotBrowser handles bookmark pre-population at the engine level through the --bot-bookmarks flag. This approach avoids the limitations of the alternatives described above.

Engine-Level Population

When --bot-bookmarks is passed at launch, BotBrowser populates the bookmark store during browser initialization, before any page loads and before any browser context is created. The bookmarks are immediately available in the bookmark bar, bookmark manager, and omnibox suggestions.

JSON Format

The --bot-bookmarks flag accepts a JSON string describing the bookmark structure:

--bot-bookmarks='[{"title":"Google","type":"url","url":"https://www.google.com"},{"title":"News","type":"folder","children":[{"title":"BBC","type":"url","url":"https://www.bbc.com"},{"title":"Reuters","type":"url","url":"https://www.reuters.com"}]}]'

The structure supports:

  • URL bookmarks: Objects with title, type: "url", and url
  • Folders: Objects with title, type: "folder", and a children array containing nested bookmarks and folders
  • Unlimited nesting: Folders can contain other folders to any depth

No Extension Required

Because bookmark population happens at the engine level, no extension is needed. This eliminates the detection surface that a bookmark-management extension would create.

Combined with Other Identity Signals

Bookmarks integrate naturally with other BotBrowser identity flags. A complete identity setup might include bookmarks, cookies, browsing history, timezone, locale, and proxy configuration, all working together to create a consistent browser session.

Configuration and Usage

Basic CLI Usage

# Simple bookmark bar with a few entries
chrome --bot-profile="/path/to/profile.enc" \
       --bot-bookmarks='[{"title":"Google","type":"url","url":"https://www.google.com"},{"title":"YouTube","type":"url","url":"https://www.youtube.com"}]'

Nested Folder Structure

chrome --bot-profile="/path/to/profile.enc" \
       --bot-bookmarks='[{"title":"Google","type":"url","url":"https://www.google.com"},{"title":"News","type":"folder","children":[{"title":"BBC","type":"url","url":"https://www.bbc.com"},{"title":"Reuters","type":"url","url":"https://www.reuters.com"}]},{"title":"Shopping","type":"folder","children":[{"title":"Amazon","type":"url","url":"https://www.amazon.com"}]}]'

Puppeteer Integration

const puppeteer = require('puppeteer-core');

const bookmarks = JSON.stringify([
  { title: 'Google', type: 'url', url: 'https://www.google.com' },
  { title: 'YouTube', type: 'url', url: 'https://www.youtube.com' },
  {
    title: 'News',
    type: 'folder',
    children: [
      { title: 'BBC', type: 'url', url: 'https://www.bbc.com' },
      { title: 'Reuters', type: 'url', url: 'https://www.reuters.com' },
    ],
  },
]);

(async () => {
  const browser = await puppeteer.launch({
    executablePath: '/path/to/botbrowser/chrome',
    args: [
      '--bot-profile=/path/to/profile.enc',
      `--bot-bookmarks=${bookmarks}`,
    ],
    headless: true,
    defaultViewport: null,
  });

  const page = await browser.newPage();
  await page.goto('https://example.com');
  console.log('Browser launched with pre-populated bookmarks');
  await browser.close();
})();

Complete Identity Setup

chrome --bot-profile="/path/to/profile.enc" \
       --bot-bookmarks='[{"title":"Google","type":"url","url":"https://www.google.com"},{"title":"Amazon","type":"url","url":"https://www.amazon.de"}]' \
       --bot-inject-random-history \
       --bot-cookies="@/path/to/cookies.json" \
       --bot-config-timezone=Europe/Berlin \
       --bot-config-locale=de-DE \
       --bot-config-languages=de-DE,de,en \
       --proxy-server=socks5://user:pass@de-proxy:1080

Verification

After launching with --bot-bookmarks, verify the bookmarks are present:

const page = await browser.newPage();

// Navigate to bookmark manager
await page.goto('chrome://bookmarks');

// Or check via the chrome.bookmarks API in a privileged context
// Bookmarks should appear in the bookmark bar immediately

You can also verify bookmarks appear in the omnibox by typing a bookmarked URL's domain and checking whether the suggestion shows the bookmark entry.

Bookmark Structure Bookmark Bar Google (url) News (folder) YouTube (url) BBC (url) Reuters (url)

Best Practices

  • Match bookmarks to the profile identity. A German user profile should have German-language bookmarks like google.de, spiegel.de, and amazon.de.
  • Vary bookmarks across identities. Each browser identity should have a unique bookmark set to create distinct profiles.
  • Keep the count realistic. A typical user has 10 to 50 bookmarks. Extremely large or empty bookmark sets look unusual.
  • Include a mix of categories. Real users bookmark a variety of sites: search engines, news, shopping, social media, and work-related pages.
  • Use folders for organization. Real bookmark bars often have folders like "Work," "Shopping," or "News." Including folders adds realism.
  • Combine with other identity flags. Bookmarks work best alongside --bot-cookies, --bot-inject-random-history, and locale/timezone configuration.

Frequently Asked Questions

What JSON format does --bot-bookmarks accept?

The flag accepts a JSON array of bookmark objects. Each object has a title, type (either "url" or "folder"), and either a url (for URL types) or children array (for folder types). The JSON is passed as a string directly in the CLI argument.

Can I load bookmarks from a file instead of inline JSON?

The --bot-bookmarks flag accepts a JSON string directly. For large bookmark sets, construct the JSON string in your automation script and pass it as a launch argument.

When are bookmarks available after launch?

Bookmarks are populated during browser initialization, before any page loads. They appear in the bookmark bar and bookmark manager immediately.

Do bookmarks persist across sessions?

Bookmarks populated through --bot-bookmarks are loaded fresh each time the browser launches. If you use the same --user-data-dir across sessions, any bookmarks added during the session will persist in that directory, but --bot-bookmarks always applies its entries on top.

Can I use --bot-bookmarks with --bot-inject-random-history?

Yes. These flags are complementary. Combining them creates a browser session with both bookmarks and browsing history, which together create a more complete browser identity.

Does --bot-bookmarks require a specific tier?

The --bot-bookmarks flag is available in the base BotBrowser package with no tier restriction.

How many bookmarks should I include?

Aim for 10 to 50 bookmarks, matching what a typical user accumulates over time. Include a mix of common sites (search engines, email, social media) and niche sites that match the profile's persona.

Summary

Pre-populating bookmarks with --bot-bookmarks adds a realistic identity layer to BotBrowser sessions. Combined with cookies, browsing history, and consistent locale settings, bookmarks help create browser profiles that reflect genuine usage patterns rather than fresh installations.

For related topics, see Cookie Management for session persistence, Synthetic Browsing History for history population, and Profile Management for organizing complete identity sets.

#bookmarks#injection#identity#browser#privacy