Skip to main content

discolike

Official Python SDK for the DiscoLike API — discover lookalike companies, enrich domain lists, match company names to domains, and find contacts, from typed Python.

For the terminal, see discolike-cli (pip install discolike-cli or uvx --from discolike-cli discolike).

Installation

pip install discolike

Requires Python 3.10+.

Authentication

export DISCOLIKE_API_KEY="dl_..."

Create a key at app.discolike.com/account/management/keys. You can also pass api_key=... explicitly to Discolike(), or run discolike auth login from the CLI to log in through the browser — the SDK then picks up the saved OAuth session and refreshes it automatically.

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)

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())

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.

Contact generation without an LLM key

contacts.generate runs on your own search provider plus either your own LLM or DiscoLike Groove, DiscoLike's native extractor. Pass NATIVE_ENGINE to skip the LLM entirely:

from discolike import NATIVE_ENGINE
from discolike.requests import ContactGenerateRequest

job = client.contacts.generate(
    ContactGenerateRequest(
        icp_text="VPs or Directors of Marketing at B2B SaaS",
        domains=["gusto.com", "rippling.com"],
        integration_id=NATIVE_ENGINE,
    )
)
result = job.wait()
print(result.title_validation)  # "none" on the native engine, "llm" on a BYOK run

The native engine returns every person the search surfaces with a title and does not validate titles against icp_text, so filter them yourself when that matters. Omit integration_id to use your default LLM integration, or native when you have none. A search provider is required either way.

ICP validation without an LLM key

validate_icp runs your ICP text against each domain on your own LLM provider key, or on DiscoLike's own ICP-fit model. Pass NATIVE_ICP_ENGINE for the latter — no LLM key, no LLM cost, and no web search on that run:

from discolike import NATIVE_ICP_ENGINE
from discolike.requests import ValidateIcpRequest

job = client.validate_icp(
    ValidateIcpRequest(
        icp_text="Cybersecurity for SMBs in North America, 50-500 employees",
        domains=["gusto.com", "rippling.com"],
        integration_id=NATIVE_ICP_ENGINE,
    )
)
print(job.column_name)  # ["ICP Fit", "ICP Score", "Reasoning"]
result = job.wait()

The engine decides the result columns, so read job.column_name instead of hardcoding them: an LLM run returns Fit / Confidence / Reasoning, the native model ICP Fit / ICP Score / Reasoning (always null). ICP Fit is Yes or No at a 0.50 threshold on ICP Score, the calibrated probability as a 0.00-1.00 string. The native model returns only that score, so Reasoning is always null — the column is there to keep the set the same shape as an LLM run, not to carry an explanation. integration_id="native-icp" also works on discogen.process for a prompt that already carries the validation structure.

Two errors are specific to the native engine: a 400 ValidationError when the ICP text does not yield a Mandatory / Reject if / Nice-to-have prompt, and a 503 ServerError when no ICP-fit engine is available. Task lifecycle, polling and statuses are the same either way.

License

MIT

Metadata

Release files for discolike 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for discolike 0.4.0
File Size Uploaded
discolike-0.4.0.tar.gz 64.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for discolike 0.4.0
File Interpreter ABI Platform
discolike-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 111.4 kB

Release files / discolike-0.4.0.tar.gz

Download URL discolike-0.4.0.tar.gz
Size 64.9 kB
Tags Source
SHA-256 checksum
How to use checksums
19c91c73e1dc992cb1d2321247242608ee84c3206a8f9d4dd9abd3f6be0f32cc
BLAKE2b-256 checksum
How to use checksums
16a2e16ed62c272cbcac9e97bf1b469f4c6ed8de0fa3ec776fa96d34cd880922
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release files / discolike-0.4.0-py3-none-any.whl

Download URL discolike-0.4.0-py3-none-any.whl
Size 46.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5491f4ac48a6b204d00c79415a4d88b378e56643cf47d12ed726dbb88c9de0bf
BLAKE2b-256 checksum
How to use checksums
30f0f68d8b0e54c594d10ea1f037779109215d23730b5611f5f0192ed6b27976
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release history Release notifications | RSS feed

0.6.0

2 release files

0.5.0

2 release files

0.4.1

2 release files

This release

0.4.0 This release

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page