websearch-tool
v1.1.0
Published
Headless Chromium web search and page fetching tool for Node.js AI agents. Returns results as clean markdown with embedded hyperlinks.
Maintainers
Readme
websearch-tool
Headless Chromium web search and page fetching for Node.js AI agents. Uses Playwright to search across multiple engines (Mojeek, Brave, Ecosia, Bing) and returns all results as clean markdown with embedded hyperlinks.
Install
npm install websearch-tool playwright
npx playwright install chromiumQuick start
import { WebSearch, SearchEngine } from "websearch-tool";
const ws = new WebSearch();
await ws.init();
// Search a single engine — returns markdown
const md = await ws.search("TypeScript tutorial", SearchEngine.Brave, 5);
console.log(md);
// Search multiple engines in parallel — deduped results with [engine] badges
const multi = await ws.searchMulti("what is a closure", [
SearchEngine.Mojeek,
SearchEngine.Brave,
]);
console.log(multi);
// Fetch a page as cleaned text
const page = await ws.fetchPage("https://example.com");
console.log(page.markdown);
// Search + fetch the top results in one call
const combo = await ws.searchAndFetch("machine learning basics", SearchEngine.Brave, 3);
console.log(combo);
await ws.close();Output format
All methods return markdown:
## Search Results for "TypeScript tutorial"
Showing 3 results:
1. **[TypeScript Tutorial](https://www.w3schools.com/typescript/)**
https://www.w3schools.com/typescript/
> You can edit TypeScript code and view the result in your browser...
2. ...Multi-engine results include engine badges:
1. **[Result Title](https://url.com)** [brave]
> Snippet from Brave...API
new WebSearch()
Create a new instance. Call init() before use.
init()
Launches headless Chromium. Call once.
search(query, engine?, maxResults?) → string
Search a single engine. Returns markdown.
| Param | Type | Default |
|-------|------|---------|
| query | string | required |
| engine | SearchEngine | SearchEngine.Mojeek |
| maxResults | number | 10 |
searchRaw(query, engine?, maxResults?) → SearchResult[]
Same as search() but returns structured data:
interface SearchResult {
title: string;
url: string;
snippet: string;
engine: SearchEngine;
}searchMulti(query, engines?, maxPerEngine?, maxTotal?) → string
Search multiple engines in parallel. Deduped, merged results with [engine] badges.
| Param | Type | Default |
|-------|------|---------|
| query | string | required |
| engines | SearchEngine[] | [Mojeek, Brave] |
| maxPerEngine | number | 7 |
| maxTotal | number | 15 |
fetchPage(url) → FetchedPage
Fetch a page and extract its content as cleaned text.
interface FetchedPage {
url: string;
title: string;
markdown: string;
}fetchPages(urls) → string
Fetch multiple pages. Returns combined markdown with ### headers and --- separators.
searchAndFetch(query, engine?, fetchCount?) → string
Search + fetch the top N results in one call. Returns markdown with search results followed by full page contents.
close()
Close the browser. Call when done.
Search Engines
| Engine | Enum | Notes |
|--------|------|-------|
| Mojeek | SearchEngine.Mojeek | Independent index, server-rendered, clean results |
| Brave | SearchEngine.Brave | Independent index, rich snippets |
| Ecosia | SearchEngine.Ecosia | Bing-powered, needs JS rendering |
| Bing | SearchEngine.Bing | Works intermittently, URL redirects |
Use with AI Agents
This package is designed for AI agent tool-use patterns:
// Agent tool definition
const searchTool = {
name: "web_search",
description: "Search the web and return results as markdown",
async execute(query: string) {
return ws.search(query, SearchEngine.Brave, 8);
},
};
const fetchTool = {
name: "fetch_page",
description: "Fetch and extract content from a URL",
async execute(url: string) {
const page = await ws.fetchPage(url);
return `## ${page.title}\n\n${page.markdown}`;
},
};Requirements
- Node.js >= 18
- Chromium (installed via
npx playwright install chromium)
License
MIT
