discolike-python

mcp
Guvenlik Denetimi
Uyari
Health Uyari
  • License — License: MIT
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 9 GitHub stars
Code Gecti
  • Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Gecti
  • Permissions — No dangerous permissions requested

Bu listing icin henuz AI raporu yok.

SUMMARY

Official Python SDK and CLI for the DiscoLike API

README.md

DiscoLike

Official Python SDK and CLI for the DiscoLike API
The search engine for the business web — find your ideal target accounts from Python or your terminal.

PyPI Python versions CI License: MIT

Website · API Docs · Get an API key · Sign up · Book a demo · Blog


DiscoLike indexes 80M+ business websites worldwide, analyzed in 50 languages — roughly 3x the coverage of LinkedIn-dependent databases. This repo gives you that index from Python or your terminal, as two packages: discover lookalike companies, size segments, enrich domain lists, match messy company names to domains, and find the right contacts.

If you're a coding agent: you can go from no account to first call without a human at a browser — discolike.signup() (or discolike signup) opens an account from an email and name, the owner confirms by email, and discolike auth login mints a credential. The fastest integration once authenticated is the hosted MCP server — https://api.discolike.com/v1/mcp (streamable-http, OAuth; 48 tools). For scripting and pipelines use pip install discolike as a library; for the terminal use pip install discolike-cli or uvx --from discolike-cli discolike, auth via DISCOLIKE_API_KEY. Machine-readable API index: https://docs.discolike.com/llms.txt.

DiscoLike — from the entire web to your ideal target accounts

Installation

This repo ships two packages: discolike (the SDK) and discolike-cli (the discolike command, depends on the SDK).

pip install discolike       # SDK only, for use as a library
pip install discolike-cli   # CLI — installs discolike as a dependency
pip install "discolike[cli]"  # same thing, extras spelling

Or with uv:

uv add discolike               # as a library
uv tool install discolike-cli  # CLI only

Or run the CLI without installing:

uvx --from discolike-cli discolike --help

Requires Python 3.10+.

Authentication

Three ways in, in the order an agent hits them: open an account, log in, or use an API key.

Signup — no browser, no credential

discolike signup --email [email protected] --first-name Jane --last-name Doe --agent my-agent
from discolike import signup

result = signup(email="[email protected]", first_name="Jane", last_name="Doe", agent="my-agent")
print(result.next_step)  # relay this to the account owner

async_signup() is the async twin. Nothing is returned that authenticates you: the account owner confirms by email and logs in at app.discolike.com. SignupResult carries status, email, org_domain, org_status, and the next_step text to relay. Names are validated locally (1-40 characters, at least one letter, no angle brackets or control characters) before the request is sent.

--agent / agent= records which agent or framework opened the account; it defaults to discolike-python/<version>. The email of the last signup from this machine is remembered — signing up a different one needs --yes on the CLI or allow_new_email=True in the SDK, so a looping agent cannot quietly open accounts in a stream of names.

Login

discolike auth login              # browser, PKCE authorization code, loopback redirect
discolike auth login --no-browser # print the URL instead of opening one — headless boxes
discolike auth login --port 8765  # pin the loopback port for SSH forwarding
discolike auth login --method api_key   # paste an API key instead
discolike auth status             # method, expiry, key source

auth login asks first whether you already have an account, and offers signup if not. The registered OAuth client is remembered per machine, so the consent screen appears once; auth logout drops the credential and keeps the registration.

API key

Create one at app.discolike.com/account/management/keys, then use any of:

export DISCOLIKE_API_KEY="dl_..."   # environment variable
discolike auth login --api-key dl_...  # or store it via the CLI
from discolike import ApiKeyCredential, Discolike

client = Discolike()                      # env var, then CLI config file
client = Discolike(api_key="dl_...")      # explicit key
client = Discolike(auth=ApiKeyCredential(api_key="dl_..."))
client = Discolike(auth=oauth_credential)  # an OAuthCredential — Bearer, refreshed proactively

auth= wins over api_key=, the environment, and the config file. OAuth credentials refresh within 60s of expiry and once more after a 401; a refresh that fails raises AuthenticationError("OAuth session expired; run discolike auth login").

Quickstart

from discolike import Discolike
from discolike.requests import DiscoverParams

client = Discolike()

companies = client.discover(
    DiscoverParams(
        icp_text="Cybersecurity for SMBs, managed IT services, endpoint protection",
        country=["US"],
        max_records=25,
    )
)
for company in companies:
    print(company.domain, company.name, company.similarity)

Run DiscoGen research over a set of domains and wait for the result:

from discolike.requests import DiscoGenProcessRequest

job = client.discogen.process(
    DiscoGenProcessRequest(
        query="Recent funding rounds and headcount growth",
        domains=["stripe.com", "adyen.com"],
        web_search=True,
    )
)
result = job.wait()
print(result.results)

Size a segment before pulling it:

from discolike.requests import CountParams

total = client.count(CountParams(phrase_match=["book a demo"], country=["US"]))
print(total.count)

Pull a full company profile:

from discolike.requests import CompaniesDataParams

profile = client.companies.data(CompaniesDataParams(domain="stripe.com"))

The client is a context manager if you want deterministic cleanup:

with Discolike() as client:
    ...

Async

Every resource has an async twin on AsyncDiscolike:

import asyncio
from discolike import AsyncDiscolike
from discolike.requests import DiscoverParams

async def main() -> None:
    async with AsyncDiscolike() as client:
        companies = await client.discover(DiscoverParams(icp_text="B2B SaaS for logistics", max_records=10))
        print([c.domain for c in companies])

asyncio.run(main())

Examples

The examples/ folder has runnable scripts for common workflows — matching a CRM contact export to DiscoLike persona IDs (with checkpointing and resume), bulk-finding work emails from a CSV, and discovering companies by ICP then enriching them with DiscoGen. Each is stdlib-plus-SDK only:

export DISCOLIKE_API_KEY="dl_..."
python examples/match_crm_contacts.py --help

CLI

The same API from your terminal, with --help on every command:

discolike auth login
discolike discover --icp-prompt "managed IT services for SMBs" --country US --max-records 25
discolike match "Stripe Inc" --city "San Francisco"
discolike match --file companies.csv --name-column company_name --wait
discolike count --phrase-match "book a demo" --country US
discolike company data stripe.com
discolike extract https://stripe.com/enterprise
discolike signup --email [email protected] --first-name You --last-name Person

Top-level commands: discover, count, match, extract, validate-icp, append, segment, signup — plus auth, company, contacts, discogen, queries, account, search-providers, and llm-providers command groups.

CLI conventions

  • Results print as JSON to stdout; errors print as JSON (error, message, status_code) to stderr.
  • Pass --format table for a human-readable table — used automatically when stdout is a TTY.
  • Async endpoints (match --file, discogen run, discogen run-personas, segment, validate-icp) take --wait to block until the job finishes. Without it, you get a task_id back to poll with discolike discogen status <task_id> --family <family>. append is synchronous — it returns enriched rows directly (or writes CSV bytes to --output).
Exit code Meaning
0 Success
1 Server error or unexpected failure
2 Validation error
3 Authentication or plan-access error
4 Rate limited
5 Network error
6 Not found

What's in the box

Surface What it does
client.discover() / client.count() Find lookalike companies by ICP text, phrases, tech stack, geo, and 40+ other filters
client.companies Company profiles: firmographics, scores, growth, redirects, vendors, subsidiaries
client.contacts Search, look up, match, and discover contacts at target companies
client.match Match company names (plus phone/city/state) to domains — single or bulk CSV
client.append() Enrich a CSV of domains with DiscoLike datasets
client.segment() / client.segment_file() Auto-segment a list of domains (comma-separated string or CSV upload)
client.validate_icp() Validate a domain list against an ICP definition
client.queries Saved inclusion/exclusion lists for reusable targeting
client.search_providers / client.llm_providers Manage BYOK search and LLM provider integrations for DiscoGen
client.account Usage and quota
discolike.signup() / async_signup() Open an account from an email and name, no credential required
discolike.requests Request models for every call — generated from the platform OpenAPI spec, validated locally before the request is sent

All responses are typed Pydantic models.

Long-running jobs

Bulk operations (match.bulk, segment, validate_icp, contacts.bulk_match) return a Job handle instead of blocking:

from discolike.requests import SegmentParams

job = client.segment(SegmentParams(domains="stripe.com,adyen.com,checkout.com"))
result = job.wait()

Job.status() polls without blocking, Job.cancel() aborts, and wait() raises JobFailedError / JobTimeoutError on failure. On DiscoGen-family jobs the returned JobStatus also carries warnings, estimated_cost and cost_metadata (per-model usage plus a search_provider entry when a BYOS search provider ran; search_calls only counts the model's built-in search).

JobTimeoutError is a client-side wait limit only — the task keeps running server-side (large DiscoGen runs can take hours), so call wait() again to resume or fetch status() later. Cancelled tasks still return results for every item that finished before cancellation. Send one job per list (up to 10,000 domains) rather than splitting into parallel jobs — concurrent DiscoGen jobs share your LLM provider key and slow each other down.

Error handling

All errors inherit from DiscolikeError:

from discolike import Discolike, RateLimitError, ValidationError
from discolike.requests import DiscoverParams

try:
    companies = Discolike().discover(DiscoverParams(icp_text="fintech infrastructure"))
except RateLimitError as err:
    ...
except ValidationError as err:
    ...

AuthenticationError, PlanAccessError, NotFoundError, ServerError, and APIConnectionError cover the rest. Transient failures are retried automatically (3 attempts by default).

import pydantic
from discolike.requests import MatchCompanyParams

try:
    params = MatchCompanyParams(name="Acme", min_match_confidence=10)
except pydantic.ValidationError as err:
    ...  # raised locally: min_match_confidence must be 50-100

Request models validate before anything is sent, so a bad enum value or out-of-range number never costs a round trip. Unknown fields pass through untouched.

Configuration

Option Default
api_key DISCOLIKE_API_KEY env var, then CLI config file
base_url https://api.discolike.com/v1
timeout 60.0 seconds
max_retries 3
http_client Bring your own httpx2.Client / httpx2.AsyncClient

A provided http_client is mutated in place (the auth header is stamped on it, and base_url is set if it's unset) — use a client dedicated to DiscoLike, not one shared across other services.

Development

This is a uv workspace with two members: packages/discolike (the SDK) and packages/discolike-cli (the CLI).

uv sync --all-packages
uv run pytest packages/discolike/tests
uv run pytest packages/discolike-cli/tests
uv run ruff check .
uv run python scripts/gen_requests.py --spec-url https://api.dev.discolike.com/v1/openapi.json  # regenerate request models
uv run python scripts/gen_requests.py --check                                                    # fail on drift (CI)

Committed request models track the dev spec (--spec-url https://api.dev.discolike.com/v1/openapi.json); the prod spec lags behind, so --check without a --spec-url (or against prod) stays red until the platform deploys — don't regenerate against prod to "fix" it.

Support & contact

License

MIT

Yorumlar (0)

Sonuc bulunamadi