Chrome Extension Search Api Patterns — Best Practices

6 min read

Chrome Search API Patterns

The chrome.search API enables programmatic web searches from your Chrome extension. This document covers patterns for implementing search functionality in extensions.

Basic Usage: chrome.search.query()

The primary method is chrome.search.query(), which triggers a search using the user’s default search engine.

chrome.search.query({
  text: 'search term',
  disposition: 'CURRENT_TAB' // or 'NEW_TAB', 'NEW_WINDOW'
});

Disposition Options

Common Use Cases

1. Search from Context Menu {#1-search-from-context-menu}

// manifest.json
{
  "permissions": ["search", "contextMenus"]
}

// background.js
chrome.contextMenus.create({
  id: 'search-selection',
  title: 'Search for: "%s"',
  contexts: ['selection']
});

chrome.contextMenus.onClicked.addListener((info, tab) => {
  if (info.menuItemId === 'search-selection') {
    chrome.search.query({
      text: info.selectionText,
      disposition: 'NEW_TAB'
    });
  }
});

2. Search from Omnibox {#2-search-from-omnibox}

// manifest.json
{
  "permissions": ["search", "omnibox"]
}

// background.js
chrome.omnibox.onInputEntered.addListener((text) => {
  chrome.search.query({
    text: text,
    disposition: 'NEW_TAB'
  });
});

3. Search Selected Text {#3-search-selected-text}

// Search selected text via keyboard shortcut or context menu
chrome.commands.onCommand.addListener((command) => {
  if (command === 'search-selection') {
    chrome.tabs.executeScript({ code: 'window.getSelection().toString()' }, (results) => {
      const selectedText = results[0];
      if (selectedText) {
        chrome.search.query({ text: selectedText, disposition: 'CURRENT_TAB' });
      }
    });
  }
});

Combining with Omnibox API for Custom Search Engines

// Multi-engine search via omnibox
chrome.omnibox.onInputChanged.addListener((text, suggest) => {
  const suggestions = [
    { content: `https://www.google.com/search?q=${text}`, description: `Google: ${text}` },
    { content: `https://www.bing.com/search?q=${text}`, description: `Bing: ${text}` },
    { content: `https://duckduckgo.com/?q=${text}`, description: `DuckDuckGo: ${text}` }
  ];
  suggest(suggestions);
});

chrome.omnibox.onInputEntered.addListener((url) => {
  chrome.tabs.update({ url });
});
const searchEngines = {
  google: (query) => `https://www.google.com/search?q=${encodeURIComponent(query)}`,
  bing: (query) => `https://www.bing.com/search?q=${encodeURIComponent(query)}`,
  duckduckgo: (query) => `https://duckduckgo.com/?q=${encodeURIComponent(query)}`,
  custom: (query) => `https://your-search-endpoint.com/search?q=${encodeURIComponent(query)}`
};

function searchWithEngine(query, engine = 'google', disposition = 'NEW_TAB') {
  const url = searchEngines[engine](query);
  chrome.search.query({ text: query, disposition });
}

Search Suggestions with chrome.omnibox.onInputChanged

chrome.omnibox.onInputChanged.addListener((text, suggest) => {
  if (text.length < 2) return;
  
  // Fetch suggestions from your API
  fetch(`https://api.example.com/suggestions?q=${text}`)
    .then(res => res.json())
    .then(suggestions => {
      const results = suggestions.map(s => ({
        content: s.url,
        description: s.title
      }));
      suggest(results);
    });
});

Search History Integration with chrome.history

// Get recent searches for suggestions
chrome.history.search({ text: query, maxResults: 10 }, (results) => {
  const searchSuggestions = results.map(r => ({
    content: r.url,
    description: r.title || query
  }));
  suggest(searchSuggestions);
});

Permission Requirements

Add "search" to your manifest.json permissions:

{
  "permissions": ["search"]
}

Limitations

Alternative: Direct API Calls

For programmatic results, call search engine APIs directly:

fetch('https://custom-search-api.example.com/search?q=query')
  .then(res => res.json())
  .then(data => {
    // Process results programmatically
    data.results.forEach(result => {
      console.log(result.title, result.url);
    });
  });

Building a Search Aggregator Popup

// popup.js - Display results from multiple engines
async function searchAllEngines(query) {
  const engines = ['google', 'bing', 'duckduckgo'];
  const results = await Promise.all(
    engines.map(engine => 
      fetch(`/api/${engine}?q=${query}`).then(r => r.json())
    )
  );
  
  // Aggregate and display results
  results.forEach((engineResults, index) => {
    displayResults(engineResults, engines[index]);
  });
}

Code Examples Summary

Pattern File Description
Context menu search examples/context-menu-search/ Right-click to search selected text
Multi-engine search examples/multi-engine-search/ Search with Google, Bing, DuckDuckGo
Omnibox search provider examples/omnibox-search/ Custom search via address bar

Cross-References

Part of the Chrome Extension Guide by theluckystrike. Built at zovo.one.