_____ __ ______ ________________
/ ___// / / / __ \/ ____/ ____/ __ \
\__ \/ / / / /_/ / /_ / __/ / /_/ /
___/ / /_/ / _, _/ __/ / /___/ _, _/
/____/\____/_/ |_/_/ /_____/_/ |_|
The official command-line interface for the Surfe API. Search contacts, enrich leads with verified emails and phone numbers, and manage your Surfe account — all from the terminal.
Built for developers, sales engineers, and AI agents that need programmatic access to Surfe's data enrichment platform.
brew install surfe/tap/surfer-cliThe formula is surfer-cli (to avoid a name clash with an unrelated
surfer in homebrew-core), but it installs the surfer command:
surfer versionTo upgrade later: brew upgrade surfer-cli. (First time only, you can also run
brew tap surfe/tap and then brew install surfer-cli.)
Download the latest binary for your platform from the Releases page.
macOS (Apple Silicon):
curl -sL https://github.com/Surfe/surfer/releases/latest/download/surfer_darwin_arm64.tar.gz | tar xz
sudo mv surfer /usr/local/bin/macOS (Intel):
curl -sL https://github.com/Surfe/surfer/releases/latest/download/surfer_darwin_amd64.tar.gz | tar xz
sudo mv surfer /usr/local/bin/Linux (amd64):
curl -sL https://github.com/Surfe/surfer/releases/latest/download/surfer_linux_amd64.tar.gz | tar xz
sudo mv surfer /usr/local/bin/git clone https://github.com/Surfe/surfer.git
cd surfer
make installRequires Go 1.26+.
surfer loginThis opens your browser to sign in via Surfe's OAuth 2.0 flow. Tokens are stored locally in ~/.surfer/tokens.json.
surfer search people --company-domains "stripe.com" --job-titles "CTO,VP Engineering"surfer enrich people --linkedin "https://linkedin.com/in/johndoe"surfer credits| Command | Description |
|---|---|
surfer login | Sign in via browser (OAuth 2.0 + PKCE) |
surfer logout | Sign out and clear local tokens |
surfer whoami | Show the account you're authenticated as |
| Command | Description |
|---|---|
surfer search people | Search contacts by job title, company, location |
surfer enrich people | Get verified emails, phones, LinkedIn profiles (add --wait to block until done) |
surfer enrich people status <id> | Check enrichment progress |
| Command | Description |
|---|---|
surfer search companies [names...] | Search companies by name, industry, size |
surfer enrich companies | Get firmographic data for a company (add --wait to block until done) |
surfer enrich companies status <id> | Check enrichment progress |
| Command | Description |
|---|---|
surfer credits | Check remaining email and mobile credits |
surfer version | Print CLI version |
surfer update | Self-update to the latest release |
surfer search people --company-domains "google.com" --seniorities "C-Level,VP" --limit 5surfer search people --job-titles "Head of Sales" --countries "US,UK,DE" --limit 20surfer enrich people --linkedin "https://linkedin.com/in/janedoe" --include-mobilesurfer enrich people --first-name Jane --last-name Doe --company-domain google.comsurfer search companies --domains "stripe.com,shopify.com"surfer search companies apple google microsoftEvery search and enrich command supports --json for full control over the request body:
surfer search people --json '{ "companies": {"domains": ["surfe.com"]}, "people": {"jobTitles": ["CTO"]}, "limit": 5}'surfer enrich people --json '{ "people": [{"linkedinUrl": "https://linkedin.com/in/johndoe"}], "include": {"email": true, "mobile": true}}'Surfer outputs JSON, so you can pipe to jq, gron, or any JSON processor:
# Get all emails from search results
surfer search people --company-domains "surfe.com"| jq '.people[].linkedInUrl'# Pretty-print company data
surfer search companies --domains "stripe.com"| jq .Surfer is designed to be used by AI agents, LLM tool-calling pipelines, and automation scripts. Every command:
- Returns structured JSON to stdout
- Accepts
--jsonfor raw API payloads (no flag parsing needed) - Uses exit code
0for success,1for errors - Supports non-interactive auth via
SURFE_API_KEYenvironment variable
For CI/CD, scripts, and AI agents that can't open a browser:
export SURFE_API_KEY="your-api-key"
surfer search people --company-domains "example.com"When SURFE_API_KEY is set, the CLI skips the OAuth flow and uses the API key directly.
{
"name": "surfe_search_people",
"description": "Search for business contacts by company, job title, or location",
"parameters": {
"json": {
"type": "string",
"description": "Raw JSON payload for POST /v2/people/search"
}
},
"command": "surfer search people --json '{json}'"
}Surfer looks for configuration in this order (highest priority first):
- Environment variables (
SURFER_AUTH_URL,SURFER_CLIENT_ID) - Config file (
~/.surfer/config.yaml) - Built-in defaults
# ~/.surfer/config.yamlauth-url: https://eu.prod.surfe.comclient-id: hubspot| Variable | Default | Description |
|---|---|---|
SURFE_API_KEY | — | API key for non-interactive auth (skips OAuth) |
SURFER_AUTH_URL | https://eu.prod.surfe.com | API and auth base URL |
SURFER_CLIENT_ID | hubspot | OAuth client ID |
Add --debug to any command to see the full HTTP request and response:
surfer --debug search people --company-domains "surfe.com"All local data is stored in ~/.surfer/ (or $XDG_CONFIG_HOME/surfer/):
~/.surfer/
config.yaml # Configuration (optional)
tokens.json # OAuth tokens (auto-managed)
version-check.json # Update check cache
surfer updateThis checks GitHub Releases for a newer version, downloads it, verifies the checksum, and replaces the binary in-place.
After every command, Surfer checks for new versions in the background (cached for 24 hours). If a newer version is available, you'll see:
🚀 A new version is available: v1.2.0 → Run 'surfer update' to upgrade.
make build # Compile binary
make install # Build + install to ~/.local/bin
make test# Run tests with coverage
make lint # Run linterContributions are welcome! Please read CONTRIBUTING.md and our Code of Conduct before opening a pull request. To report a security issue, see SECURITY.md.
Licensed under the MIT License. Copyright © 2026 Surfe.