Skip to main content

Overview

The Browser IPC namespace provides APIs for managing browser profiles, tabs, navigation, and page content. These APIs are available through the window.flow.browser, window.flow.tabs, and window.flow.navigation objects.

Browser API

The window.flow.browser API manages browser profiles and windows.

Source Files

  • Interface: src/shared/flow/interfaces/browser/browser.ts
  • Handler: src/main/ipc/browser/browser.ts
  • Preload: src/preload/index.ts:411-421

Methods

loadProfile
(profileId: string) => Promise<void>
Loads a profile, initializing its session and making it available for use.
await window.flow.browser.loadProfile("profile-123");
profileId
string
required
The ID of the profile to load
unloadProfile
(profileId: string) => Promise<void>
Unloads a profile, cleaning up its session and resources.
await window.flow.browser.unloadProfile("profile-123");
profileId
string
required
The ID of the profile to unload
createWindow
() => void
Creates a new browser window.
window.flow.browser.createWindow();

Tabs API

The window.flow.tabs API provides comprehensive tab management capabilities.

Source Files

  • Interface: src/shared/flow/interfaces/browser/tabs.ts
  • Handler: src/main/ipc/browser/tabs.ts
  • Preload: src/preload/index.ts:423-483

Data Methods

getData
() => Promise<WindowTabsData>
Retrieves all tab data for the current window, including tabs, tab groups, focused tabs, and active tabs.
const tabsData = await window.flow.tabs.getData();
console.log("Tabs:", tabsData.tabs);
console.log("Tab Groups:", tabsData.tabGroups);
console.log("Focused Tabs:", tabsData.focusedTabIds);
console.log("Active Tabs:", tabsData.activeTabIds);
tabs
TabData[]
Array of tab data objects containing id, title, url, favicon, loading state, etc.
tabGroups
TabGroupData[]
Array of tab group data objects
focusedTabIds
WindowFocusedTabIds
Map of space ID to focused tab ID
activeTabIds
WindowActiveTabIds
Map of space ID to active tab ID(s)
onDataUpdated
IPCListener<[WindowTabsData]>
Subscribes to full tab data refresh events. Called when structural changes occur (tabs added/removed, active tab changed, etc.).
const unsubscribe = window.flow.tabs.onDataUpdated((data) => {
  console.log("Tabs updated:", data);
  // Update your UI with the new data
});

// Later: clean up
unsubscribe();
This listener receives full WindowTabsData refreshes. For more efficient content-only updates (title, url, loading state), use onTabsContentUpdated instead.
onTabsContentUpdated
IPCListener<[TabData[]]>
Subscribes to lightweight content-only tab updates. Receives only the tabs whose content (title, url, isLoading, etc.) changed, without a full refresh.
const unsubscribe = window.flow.tabs.onTabsContentUpdated((updatedTabs) => {
  console.log("Content updated for tabs:", updatedTabs);
  // Merge these updates into your existing state
});
The IPC layer automatically debounces updates (80ms) and batches content changes to reduce overhead. If a structural change occurs during the debounce window, it absorbs pending content changes.

Tab Operations

newTab
(url?: string, isForeground?: boolean, spaceId?: string) => Promise<boolean>
Creates a new tab in the specified space.
// Create tab in background
await window.flow.tabs.newTab("https://example.com", false, spaceId);

// Create tab in foreground
await window.flow.tabs.newTab("https://example.com", true, spaceId);

// Create blank tab
await window.flow.tabs.newTab();
url
string
The URL to load in the new tab. Omit to create a blank tab.
isForeground
boolean
Whether to make the tab active (foreground). Defaults to false.
spaceId
string
The ID of the space to create the tab in. Uses current space if not provided.
switchToTab
(tabId: number) => Promise<boolean>
Switches to (activates) the specified tab.
await window.flow.tabs.switchToTab(tabId);
closeTab
(tabId: number) => Promise<boolean>
Closes the specified tab.
await window.flow.tabs.closeTab(tabId);
moveTab
(tabId: number, newPosition: number) => Promise<boolean>
Moves a tab to a new position within its current space.
await window.flow.tabs.moveTab(tabId, 3);
The handler automatically normalizes positions after reordering to prevent drift. If the tab is in a group, all group members are moved together.
moveTabToWindowSpace
(tabId: number, spaceId: string, newPosition?: number) => Promise<boolean>
Moves a tab to a different space, optionally at a specific position.
await window.flow.tabs.moveTabToWindowSpace(tabId, "space-456", 0);
batchMoveTabs
(tabIds: number[], spaceId: string, newPositionStart?: number) => Promise<boolean>
Moves multiple tabs to a new space in one operation.
await window.flow.tabs.batchMoveTabs([tab1, tab2, tab3], "space-789", 5);

Tab Context Menu

showContextMenu
(tabId: number) => void
Displays the native context menu for a tab.
window.flow.tabs.showContextMenu(tabId);

Tab State

setTabMuted
(tabId: number, muted: boolean) => Promise<boolean>
Sets the audio muted state of a tab.
// Mute tab
await window.flow.tabs.setTabMuted(tabId, true);

// Unmute tab
await window.flow.tabs.setTabMuted(tabId, false);
disablePictureInPicture
(goBackToTab: boolean) => Promise<boolean>
Disables Picture-in-Picture mode for a tab.
// Disable PiP and return to tab
await window.flow.tabs.disablePictureInPicture(true);

// Disable PiP without switching tabs
await window.flow.tabs.disablePictureInPicture(false);
This method will only work if the tab is currently in Picture-in-Picture mode. It’s tightly secured and will fail otherwise.

Recently Closed Tabs

getRecentlyClosed
() => Promise<RecentlyClosedTabData[]>
Retrieves all recently closed tabs, sorted by most recently closed first.
const recentlyClosed = await window.flow.tabs.getRecentlyClosed();
console.log("Recently closed:", recentlyClosed);
restoreRecentlyClosed
(uniqueId: string) => Promise<boolean>
Restores a recently closed tab by its unique ID.
const recentlyClosed = await window.flow.tabs.getRecentlyClosed();
if (recentlyClosed.length > 0) {
  await window.flow.tabs.restoreRecentlyClosed(recentlyClosed[0].tabData.uniqueId);
}
clearRecentlyClosed
() => Promise<boolean>
Clears the list of recently closed tabs.
await window.flow.tabs.clearRecentlyClosed();
The window.flow.navigation API handles page navigation within tabs.

Source Files

  • Interface: src/shared/flow/interfaces/browser/navigation.ts
  • Handler: src/main/ipc/browser/navigation.ts
  • Preload: src/preload/index.ts:495-512

Methods

goTo
(url: string, tabId?: number) => void
Navigates to a specific URL. If no tab ID is provided, navigates the focused tab.
// Navigate focused tab
window.flow.navigation.goTo("https://example.com");

// Navigate specific tab
window.flow.navigation.goTo("https://example.com", tabId);
stopLoadingTab
(tabId: number) => void
Stops loading the specified tab.
window.flow.navigation.stopLoadingTab(tabId);
reloadTab
(tabId: number) => void
Reloads the specified tab.
window.flow.navigation.reloadTab(tabId);
getTabNavigationStatus
(tabId: number) => Promise<TabNavigationStatus | null>
Gets the navigation status of a tab, including navigation history and back/forward capabilities.
const status = await window.flow.navigation.getTabNavigationStatus(tabId);
if (status) {
  console.log("Can go back:", status.canGoBack);
  console.log("Can go forward:", status.canGoForward);
  console.log("Current page:", status.navigationHistory[status.activeIndex]);
}
navigationHistory
NavigationEntry[]
Array of navigation entries, where index 0 is the earliest visited page
activeIndex
number
Index of the currently active navigation entry
canGoBack
boolean
Whether the tab can navigate back
canGoForward
boolean
Whether the tab can navigate forward
goToNavigationEntry
(tabId: number, index: number) => void
Navigates to a specific entry in the tab’s navigation history.
const status = await window.flow.navigation.getTabNavigationStatus(tabId);
// Go to the first page in history
window.flow.navigation.goToNavigationEntry(tabId, 0);

Complete Example

Here’s a complete React component that uses the Browser IPC APIs:
import { useEffect, useState } from "react";

function BrowserUI() {
  const [tabs, setTabs] = useState([]);
  const [activeTabId, setActiveTabId] = useState(null);
  
  useEffect(() => {
    // Initial data fetch
    window.flow.tabs.getData().then(data => {
      setTabs(data.tabs);
      // Get the first active tab from any space
      const firstSpace = Object.keys(data.activeTabIds)[0];
      if (firstSpace) {
        const activeIds = data.activeTabIds[firstSpace];
        setActiveTabId(activeIds[0]);
      }
    });
    
    // Subscribe to structural updates
    const unsubscribeFull = window.flow.tabs.onDataUpdated(data => {
      setTabs(data.tabs);
    });
    
    // Subscribe to content updates
    const unsubscribeContent = window.flow.tabs.onTabsContentUpdated(updatedTabs => {
      setTabs(prevTabs => 
        prevTabs.map(tab => {
          const updated = updatedTabs.find(u => u.id === tab.id);
          return updated || tab;
        })
      );
    });
    
    return () => {
      unsubscribeFull();
      unsubscribeContent();
    };
  }, []);
  
  const handleNewTab = async () => {
    await window.flow.tabs.newTab("https://example.com", true);
  };
  
  const handleCloseTab = async (tabId) => {
    await window.flow.tabs.closeTab(tabId);
  };
  
  const handleSwitchTab = async (tabId) => {
    await window.flow.tabs.switchToTab(tabId);
    setActiveTabId(tabId);
  };
  
  const handleReload = () => {
    if (activeTabId) {
      window.flow.navigation.reloadTab(activeTabId);
    }
  };
  
  const handleNavigate = (url) => {
    window.flow.navigation.goTo(url, activeTabId);
  };
  
  return (
    <div>
      <div className="tab-bar">
        {tabs.map(tab => (
          <div 
            key={tab.id}
            className={tab.id === activeTabId ? "tab active" : "tab"}
            onClick={() => handleSwitchTab(tab.id)}
            onContextMenu={() => window.flow.tabs.showContextMenu(tab.id)}
          >
            {tab.faviconURL && <img src={tab.faviconURL} alt="" />}
            <span>{tab.title}</span>
            <button onClick={(e) => {
              e.stopPropagation();
              handleCloseTab(tab.id);
            }}>×</button>
          </div>
        ))}
        <button onClick={handleNewTab}>+</button>
      </div>
      
      <div className="toolbar">
        <button onClick={handleReload}>Reload</button>
        <input 
          type="text" 
          onKeyPress={(e) => {
            if (e.key === 'Enter') {
              handleNavigate(e.target.value);
            }
          }}
        />
      </div>
    </div>
  );
}

App IPC

Application info and clipboard APIs

Window IPC

Window management and controls

IPC Overview

Learn about Flow’s IPC architecture

Build docs developers (and LLMs) love