Overview
Ferret is a declarative-first, expression-oriented embedded language and runtime for data automation. You write the query — FQL — and the runtime works out how to execute it, across browsers, HTTP APIs, databases, documents and whatever custom sources the host application exposes. The original use case was web scraping that stays readable: rather than a script of imperative navigate-click-wait steps, a page extraction is a query that describes the shape of the data you want.
The runtime is a Go library, not a standalone binary, and that is the point. An application embeds the engine and decides exactly which functions, modules, data and external operations a given program may touch — a capability-based model where host values expose application objects and resources directly to FQL. Programs compile to bytecode and can be reused across isolated execution sessions, so the same plan runs repeatedly without recompilation. A separate CLI, test runner (`lab`) and web worker live in sibling repositories.
The repository's main branch carries Ferret v2, an alpha with a new architecture and public API; v1 remains available on its own branch. v2 adds domain-oriented orchestration and constrained mutable state on top of the declarative core, for automation that cannot be expressed as a pure data transformation, plus event-driven synchronisation and managed lifecycles for files, connections, cursors and streams. Existing v1 integrations migrate in two stages via a `compat` module and a `ferret migrate` command. Ferret is Apache-2.0 licensed.
What it does
- FQL, a purpose-built declarative language for querying, transforming, synchronising and automating structured data — deliberately focused rather than general-purpose
- One query model over browsers, APIs, databases, documents and custom sources, so the source changes without the query shape changing
- Embeddable Go runtime with reusable compiled plans and isolated execution sessions
- Capability-based host values: the embedding application decides exactly which functions, modules, data and external operations a program can reach
- Bytecode VM with portable, precompiled programs for efficient repeated execution
- Event-driven synchronisation and dispatch, plus managed resource lifecycles for files, connections, cursors and streams
Getting started
Ferret is consumed as a Go module. The v2 flow is engine → compile query → create session → run.
Add the module
New projects should use the native v2 API directly.
go get github.com/MontFerret/ferret/v2@latestCompile and run a query
Create an engine, compile a source into a plan, open a session against that plan, and run it. Each object is closed in reverse order.
package main
import (
"context"
"fmt"
"log"
"github.com/MontFerret/ferret/v2"
)
func main() {
ctx := context.Background()
eng, err := ferret.New()
if err != nil {
log.Fatal(err)
}
defer eng.Close()
plan, err := eng.Compile(ctx, ferret.NewAnonymousSource(`return 1 + 1`))
if err != nil {
log.Fatal(err)
}
defer plan.Close()
session, err := plan.NewSession(ctx)
if err != nil {
log.Fatal(err)
}
defer session.Close()
output, err := session.Run(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(output.Content))
}Try the language without writing Go
The project hosts a playground at ferretlang.org/try, and ships a separate CLI, a `lab` test runner and a web worker in sibling repositories.
Migrate an existing v1 integration
`ferret migrate` rewrites documented v1 imports to their v2 compatibility packages and updates go.mod/go.sum. It is a mechanical first stage — it does not convert application logic to the native v2 API, and unsupported imports are reported for manual follow-up.
ferret migrate --dry-run # list the files that would change
ferret migrate --print # print a unified diff, change nothing
ferret migrate # applyKnow what you are adopting
Ferret v2 is in active development and released as alpha; some APIs and language features may still change before the stable v2 release. Projects that need stability today can stay on the v1 branch.
Commands and code are distilled from the project's own documentation — always check the official repo for the latest.
When to use it
- Extract structured records from JavaScript-heavy pages with a query that describes the data rather than a script of browser steps
- Embed a sandboxed automation language in a Go application and expose only the operations that application is willing to allow
- Run the same compiled extraction plan repeatedly across isolated sessions in a crawling or monitoring service
- Join data from a browser, an HTTP API and a database in one query instead of three connectors and glue code
How Ferret compares
Ferret alongside other open-source web scraping & crawling tools AI/TLDR tracks, ranked by GitHub stars.
| Tool | Stars | What it does |
|---|---|---|
| Firecrawl | ★ 183k | A crawling service and API that converts whole websites into clean Markdown or structured JSON ready for LLMs. |
| Agent Reach | ★ 84.4k | A capability layer that installs, health-checks and routes readers so a CLI agent can read and search web pages, YouTube, RSS, GitHub, Reddit, Twitter/X and more without API fees. |
| Crawl4AI | ★ 84k | A local-first Python web crawler that turns pages into clean Markdown for use in RAG and LLM pipelines. |
| Scrapling | ★ 82.8k | A Python web scraping framework whose parser relocates your elements when pages change, with stealthy fetchers and a Scrapy-like spider engine for full crawls. |
| Scrapy | ★ 64.4k | A mature Python framework for writing fast spiders that crawl websites and extract structured data at scale. |
| changedetection.io | ★ 34.4k | A self-hosted web page change monitor with XPath/CSS/jq filters, browser steps and restock alerts, which can route every diff through an LLM to suppress noise. |
| ScrapeGraphAI | ★ 31.2k | A Python library that uses LLMs and a graph pipeline to extract data from pages based on natural-language prompts. |
| Ferret | ★ 6k | A declarative query language and embeddable Go runtime for pulling structured data out of browsers, APIs, databases and documents |