{"slug": "show-hn-ember-lightweight-headless-browser-for-ai-agents-17mb-idle", "title": "Show HN: Ember – Lightweight headless browser for AI agents (17MB idle)", "summary": "Ember, a lightweight open-source headless browser for AI agents, launches at just 17 MB idle, significantly smaller than alternatives like Chromium-based tools. It requires no Docker or API keys, supporting scraping, search, crawling, and interactive browser control via a single pip install. The tool aims to make web automation accessible on low-resource devices like VPS, laptops, or Raspberry Pis.", "body_md": "\n\n```\n  ███████╗███╗   ███╗██████╗ ███████╗██████╗ \n  ██╔════╝████╗ ████║██╔══██╗██╔════╝██╔══██╗\n  █████╗  ██╔████╔██║██████╔╝█████╗  ██████╔╝\n  ██╔══╝  ██║╚██╔╝██║██╔══██╗██╔══╝  ██╔══██╗\n  ███████╗██║ ╚═╝ ██║██████╔╝███████╗██║  ██║\n  ╚══════╝╚═╝     ╚═╝╚═════╝ ╚══════╝╚═╝  ╚═╝\n```\n\n**Open source, lightweight headless browser for AI agents.**\n\n```\npip install ember-browser\n```\n\n*No Docker. No API key to start.*\n\nMost web tools for agents ship with Chromium (~281 MB) or require Docker just to get started. We needed something an agent could use on a VPS, a laptop, or a Raspberry Pi without thinking about it.\n\nember runs at ~17 MB idle. It decides whether a page needs a browser — you just pass it a URL.\n\n| ember | Crawl4AI | Firecrawl OSS | Playwright | |\n|---|---|---|---|---|\n| Setup | `pip install` |\n`pip install` |\nDocker + Redis + Node | `pip` + browser install |\n| Package size | ~54 MB | ~200–350 MB | Thin client only | ~47 MB |\n| Browser binary | Lightpanda ~12 MB | Chromium ~281 MB | Chromium ~281 MB | Chromium ~281 MB |\n| Docker required | No | No | Yes | No |\n| API key required | No | No | No | No |\n| MCP server | Yes | No | Yes | Yes |\n| Search built-in | Yes | No | Yes | No |\n| Zero-infra self-host | Yes | Yes | No | Yes |\n\n```\npip install ember-browser\nember version                  # verify install\n\nember                          # start the interactive session\nember url https://example.com  # or run a one-shot command\nember serve                    # start the REST API\n```\n\n`ember`\n\nwith no arguments opens a persistent session. Commands and a save guide are shown on startup — no need to type `help`\n\nfirst.\n\n```\n  ███████╗███╗   ███╗██████╗ ███████╗██████╗\n  ██╔════╝████╗ ████║██╔══██╗██╔════╝██╔══██╗\n  █████╗  ██╔████╔██║██████╔╝█████╗  ██████╔╝\n  ██╔══╝  ██║╚██╔╝██║██╔══██╗██╔══╝  ██╔══██╗\n  ███████╗██║ ╚═╝ ██║██████╔╝███████╗██║  ██║\n  ╚══════╝╚═╝     ╚═╝╚═════╝ ╚══════╝╚═╝  ╚═╝\n\n  v0.1.0  lightweight headless browser for AI agents\n\n  url        <url>              scrape a page to markdown\n  search     <query>            web search\n  crawl      <url>              crawl a whole website\n  map        <url>              discover all URLs on a site\n  interact   <url>              control a browser with natural language\n  extract    <url>              pull structured data with an LLM\n  batch      <urls.txt>         scrape many URLs concurrently\n\n  ─── saving results ───────────────────────────────────────────\n  one result   url example.com -o page.md\n  everything   output ./research/  then all results auto-save\n  last result  save page.md        after any command\n\nember › url andausman.com\nember › save page.md\n\nember › output ./research/       # auto-save everything from here\nember/research › search \"python asyncio\" -n 10\nember/research › crawl docs.example.com\nember/research › output clear    # stop auto-saving\nember › quit\n```\n\nEvery command works standalone too:\n\n```\nember url https://example.com                         # scrape a page\nember search \"AI agents python\" -n 10                 # web search\nember crawl https://docs.example.com --max-pages 20   # crawl a site\nember map https://example.com                         # discover all URLs\nember interact https://amazon.com \\\n  --prompt \"find a mechanical keyboard under $100\"\nember extract https://example.com/pricing \\\n  --prompt \"list all plans and prices as JSON\"\n```\n\nAll commands accept `-o`\n\nto save that run:\n\n```\nember url https://example.com -o page.md\nember search \"python\" -o results.json\nember crawl https://docs.example.com -o ./pages/   # one .md per page\nember map https://example.com -o urls.txt\nember extract https://example.com -o data.json\n```\n\nSet a default save directory so you never need `-o`\n\n:\n\n```\nember config --save-dir ./research/    # persists across sessions\nember config                           # show current settings\nember config --save-dir \"\"             # clear it\n```\n\nOr use an environment variable for the current shell:\n\n```\nEMBER_SAVE_DIR=./out ember url https://example.com\n```\n\nIn a session, the three ways to save:\n\n```\nember › url example.com -o page.md     # save just this run\nember › save page.md                   # save the last result\nember › output ./research/             # auto-save all results from now on\n# urls.txt — one URL per line, # = comment\nember batch urls.txt                      # 5 concurrent by default\nember batch urls.txt -c 20 -o ./pages/   # 20 parallel, save to dir\npython\nfrom emb.scrape import scrape_url, scrape_markdown\nfrom emb.search import search\nfrom emb.crawl import crawl\nfrom emb.map import map_url\n\n# Scrape a page → ScrapeResult\nresult = scrape_url(\"https://example.com\")\nprint(result.markdown)   # full page content as markdown\nprint(result.title)      # page title\nprint(result.success)    # True / False\n\n# Just the markdown text\nmd = scrape_markdown(\"https://example.com\")\n\n# Crawl a site\nresult = crawl(\"https://docs.example.com\", max_pages=20, max_depth=3)\nfor page in result.pages:\n    print(page.url, len(page.markdown))\n\n# Discover URLs\nresult = map_url(\"https://example.com\", max_links=100)\nprint(result.links)   # list[str]\n\n# Search the web\nresults = search(\"python asyncio tutorial\", limit=5)\nfor r in results:\n    print(r.title, r.url)\n\n# Browser interaction with natural language\nfrom emb.interact import interact\n\nresult = interact(\"https://example.com\", prompt=\"click the login button\")\nprint(result.content)   # what the agent did / saw\n\n# LLM-powered structured extraction\nfrom emb.agent import extract\n\ndata = extract(\"https://example.com/pricing\", prompt=\"list all plans and prices\")\nprint(data)   # dict\npython\nimport asyncio\nfrom emb.scrape import scrape_url_async\n\nasync def main():\n    results = await asyncio.gather(\n        scrape_url_async(\"https://example.com\"),\n        scrape_url_async(\"https://httpbin.org/get\"),\n    )\n    for r in results:\n        print(r.url, r.success)\n\nasyncio.run(main())\nember serve               # http://127.0.0.1:51251\nember serve --port 8080   # custom port\n\nEMBER_API_KEY=your-secret ember serve   # require auth\ncurl -X POST http://localhost:51251/scrape \\\n  -H \"Content-Type: application/json\" \\\n  -H \"X-API-Key: your-secret\" \\\n  -d '{\"url\": \"https://example.com\"}'\n\ncurl -X POST http://localhost:51251/search \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"query\": \"AI agents\", \"limit\": 5}'\n\ncurl -X POST http://localhost:51251/crawl \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"url\": \"https://docs.example.com\", \"max_pages\": 10}'\n```\n\nEndpoints: `/scrape`\n\n`/search`\n\n`/crawl`\n\n`/map`\n\n`/interact`\n\n`/extract`\n\n`/agent`\n\n`/health`\n\nAdd to your Hermes config, OpenClaw config, Mercury config, or any MCP-compatible host:\n\n```\n{\n  \"mcpServers\": {\n    \"ember\": {\n      \"command\": \"ember\",\n      \"args\": [\"mcp\"]\n    }\n  }\n}\n```\n\nWorks with Hermes, OpenClaw, Mercury, and any MCP-compatible host.\n\nAvailable tools: `scrape`\n\n, `search_web`\n\n, `crawl_site`\n\n, `map_site`\n\n, `batch_scrape`\n\n, `interact_page`\n\n, `extract_data`\n\n.\n\nOnce connected, your agent can use ember tools directly in conversation:\n\n```\nUser: Summarise the latest posts on Hacker News\n\nAgent: [calls scrape(\"https://news.ycombinator.com\")]\n       → returns full page markdown with titles, scores, links\n\nAgent: Here are today's top stories on Hacker News: ...\nUser: Find 5 articles about AI agents and scrape each one\n\nAgent: [calls search_web(\"AI agents 2025\", limit=5)]\n       → returns list of {title, url, description}\n\nAgent: [calls batch_scrape([\"url1\", \"url2\", ...])]\n       → returns markdown for each page\n\nAgent: Here's a summary across all 5 articles: ...\n```\n\nNot every page needs a browser. ember knows the difference.\n\n**Tier 1 — trafilatura** handles ~89% of the web: blogs, news, documentation, docs sites, GitHub. Pure HTTP, no browser process, no memory overhead.\n\n**Tier 2 — Lightpanda** handles JavaScript-heavy pages, SPAs, and interactive content. It's a real browser engine written in Zig, built for machines rather than humans — 20 MB total. ember downloads and caches it automatically on first use, and only falls back to it when tier 1 produces thin content.\n\nMost requests never reach the browser.\n\n| State | RAM |\n|---|---|\n| Idle | ~17 MB |\n| Scraping a static page | ~20 MB |\n| Running the browser | ~140 MB |\n\nFirecrawl needs 4–8 GB in Docker. Crawl4AI imports at 171 MB before scraping anything. ember fits where your agent already runs.\n\n| Variable | Default | Description |\n|---|---|---|\n`EMBER_SAVE_DIR` |\n(none) |\nDefault directory for saved results. Overrides `ember config --save-dir` for the current shell. |\n`EMBER_API_KEY` |\n(none) |\nEnables API key auth on the REST server (`X-API-Key` header). |\n`EMBER_PORT` |\n`51251` |\nDefault port for `ember serve` . Overridden by `--port` flag. |\n`EMBER_INTERACT_PROVIDER` |\n`openai` |\nLLM provider for `interact` (`openai` , `anthropic` , `ollama` , etc.). |\n`EMBER_LLM_API_KEY` |\n(none) |\nAPI key for LLM-powered extraction. |\n`EMBER_LLM_BASE_URL` |\n`https://api.openai.com/v1` |\nLLM API endpoint for extraction. |\n`EMBER_LLM_MODEL` |\n`gpt-4o-mini` |\nModel used by `extract` . |\n`EMBER_LIGHTPANDA_PATH` |\n(auto) |\nPath to a custom Lightpanda binary. Skips auto-download if set. |\n\n[MIT](/andalabx/ember/blob/main/LICENSE) — open source forever.", "url": "https://wpnews.pro/news/show-hn-ember-lightweight-headless-browser-for-ai-agents-17mb-idle", "canonical_source": "https://github.com/andalabx/ember", "published_at": "2026-07-09 11:32:52+00:00", "updated_at": "2026-07-09 11:41:57.146594+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools"], "entities": ["Ember", "Lightpanda", "Chromium", "Crawl4AI", "Firecrawl", "Playwright"], "alternates": {"html": "https://wpnews.pro/news/show-hn-ember-lightweight-headless-browser-for-ai-agents-17mb-idle", "markdown": "https://wpnews.pro/news/show-hn-ember-lightweight-headless-browser-for-ai-agents-17mb-idle.md", "text": "https://wpnews.pro/news/show-hn-ember-lightweight-headless-browser-for-ai-agents-17mb-idle.txt", "jsonld": "https://wpnews.pro/news/show-hn-ember-lightweight-headless-browser-for-ai-agents-17mb-idle.jsonld"}}