synthient

package module
v2.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 3, 2026 License: Apache-2.0 Imports: 24 Imported by: 0

README

go-synthient

godoc go.mod version report card

Synthient SDK for Go.

Installation

go get -u github.com/synthient/go-synthient/v2

Requires Go 1.23 or later (real-time streams use iter.Seq2).

Getting started

All requests are made through a synthient.Client. Create one with your API key:

client := synthient.NewClient(os.Getenv("SYNTHIENT_API_KEY"))

Pass nil as the last argument to any method to use default request options, or supply a *synthient.RequestOptions to attach a context for cancellation and timeouts:

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
opts := &synthient.RequestOptions{Context: ctx}

IP lookup

client.GetIP returns enrichment data for a single address:

ip, err := client.GetIP("213.149.183.127", nil)
if err != nil {
    log.Fatal(err)
}
fmt.Println(ip.Intelligence.RiskScore, ip.Network.Isp, ip.Location.Country)

client.GetIPs looks up multiple addresses in one request:

results, err := client.GetIPs([]string{"8.8.8.8", "1.1.1.1"}, nil)
if err != nil {
    log.Fatal(err)
}
for _, ip := range results {
    fmt.Println(ip.IP, ip.Intelligence.RiskScore)
}

Domain lookup

client.GetDomain returns traffic statistics, geo distribution, and recent events for a domain:

domain, err := client.GetDomain("google.com", nil)
if err != nil {
    log.Fatal(err)
}
fmt.Println(domain.Stats.Events24H, domain.Status)

Account

client.GetAccount returns profile and quota details for the authenticated user:

account, err := client.GetAccount(nil)
if err != nil {
    log.Fatal(err)
}
fmt.Println(account.Organization.Name, account.LookupQuota.Credits)

Parquet snapshot feeds

Stream identifiers: proxies, anonymizers, torrents, honeypot_http, honeypot_https, honeypot_dns, honeypot_adb.

List snapshots

client.FeedSnapshots returns a paginated list of available daily and hourly snapshots, newest-first:

var cursor string
for {
    page, err := client.FeedSnapshots("proxies", &synthient.FeedSnapshotsOptions{
        Limit:  50,
        Cursor: cursor,
    }, nil)
    if err != nil {
        log.Fatal(err)
    }
    for _, snap := range page.Feeds {
        fmt.Println(snap.Kind, snap.ID, snap.SizeBytes)
    }
    if page.NextCursor == "" {
        break
    }
    cursor = page.NextCursor
}
Snapshot metadata

client.FeedSnapshotMeta returns the checksum, row count, byte size, and parquet schema for a snapshot. date accepts "latest", "YYYY-MM-DD", or "YYYY-MM-DD/HH":

meta, err := client.FeedSnapshotMeta("proxies", "latest", nil)
if err != nil {
    log.Fatal(err)
}
fmt.Println(meta.Rows, meta.Checksum)
for _, field := range meta.Schema.Fields {
    fmt.Println(field.Name, field.Type)
}
Download a snapshot

client.DownloadFeedSnapshot follows the API's 307 redirect and returns a streaming reader for the parquet file. The caller must close it.

Pass a non-nil hour pointer (0–23) to address a specific hourly snapshot within the current UTC day:

// latest hourly
r, err := client.DownloadFeedSnapshot("proxies", "latest", nil, nil)
if err != nil {
    log.Fatal(err)
}
defer r.Close()

f, _ := os.Create("proxies-latest.parquet")
defer f.Close()
io.Copy(f, r)
// specific hour
hour := 21
r, err := client.DownloadFeedSnapshot("proxies", "2026-05-07", &hour, nil)

Real-time firehose streams

All stream methods return an iter.Seq2[T, error] that yields one event per NDJSON line. Break out of the loop or cancel the context to stop the stream.

Proxies
for event, err := range client.StreamProxy(nil) {
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(event.IP, event.Provider, event.CountryCode)
}

ProxyEvent fields: IP, Provider, Type, Timestamp, CountryCode, ASN.

Anonymizers
for event, err := range client.StreamAnonymizer(nil) {
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(event.RangeStart, event.RangeEnd, event.Type, event.Provider)
}

AnonymizerEvent fields: RangeStart, RangeEnd, Provider, Type, Timestamp.

Torrents
for event, err := range client.StreamTorrent(nil) {
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%s %s peers=%d\n", event.InfoHash, event.Name, len(event.Peers))
}

TorrentEvent fields: InfoHash, Name, MagnetURI, TotalSize, PieceLength, FileCount, Files, Peers, Timestamp.

Helios sensor streams

HTTP captures
for event, err := range client.StreamHeliosHTTP(nil) {
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(event.Details.Method, event.Details.URI, event.Domain)
}

HeliosHTTPEvent fields: Timestamp, Domain, Port, TunnelID, Protocol, Details (method, URI, version, headers map), Raw, Meta (pool ID, provider, proxy IP, server).

TLS ClientHello captures
for event, err := range client.StreamHeliosTLS(nil) {
    if err != nil {
        log.Fatal(err)
    }
    if event.Details == nil {
        continue // parse failed
    }
    fmt.Println(event.Domain, event.Details.HandshakeVersion, len(event.Details.CipherSuites))
}

HeliosTLSEvent carries the fully parsed ClientHello in Details (*HeliosTLSDetails), which is nil when the sensor could not parse the handshake. Details includes cipher suites, extensions, supported groups, signature algorithms, key share groups, supported versions, and boolean handshake flags (extended_master_secret, renegotiation_info, has_grease, etc.).

gRPC schema introspection

client.GRPCSchema uses gRPC server reflection to fetch protobuf file descriptors from grpc.synthient.com:443. Pass nil to resolve all services, or supply a list of fully-qualified service names:

ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel()

// all services
result, err := client.GRPCSchema(ctx, nil)
if err != nil {
    if msg := synthient.ExplainGRPCError(err); msg != "" {
        log.Fatal(msg)
    }
    log.Fatal(err)
}
for _, svc := range result.Symbols {
    fmt.Println(svc)
}
for _, f := range result.DescriptorSet.File {
    fmt.Println(f.GetName(), f.GetPackage())
}
// specific symbol
result, err := client.GRPCSchema(ctx, &synthient.GRPCSchemaOptions{
    Symbols: []string{"synthient.lookup.v1.LookupService"},
})

GRPCSchemaResult fields:

Field Type Description
Endpoint string Normalized address that was queried
Symbols []string Service symbols that were resolved
DescriptorSet *descriptorpb.FileDescriptorSet All file descriptors in topological order

NormalizeGRPCEndpoint and ExplainGRPCError are exported for use in CLI applications that need custom endpoint handling or human-readable error messages.

Note: GRPCSchema adds google.golang.org/grpc and google.golang.org/protobuf to your module's dependency graph. If you only need REST API access these are still pulled in transitively, but no gRPC connections are made unless you call GRPCSchema.

Client customization

Override BaseAPI to point at a self-hosted endpoint:

client := synthient.NewClient("SECRET TOKEN")
client.BaseAPI.Host = "synthient.myserver.com"

Set a custom HTTP client for timeouts or proxies:

client.HttpClient = &http.Client{Timeout: 30 * time.Second}

Documentation

Index

Constants

View Source
const DefaultGRPCEndpoint = "grpc.synthient.com:443"

DefaultGRPCEndpoint is the default Synthient gRPC server address.

Variables

View Source
var (
	ErrNoToken    = errors.New("no token provided for client")
	ErrFileExists = errors.New("file already exists")
)
View Source
var (
	ErrBadRequest           = errors.New("invalid input parameters")
	ErrUnauthorized         = errors.New("no api key was provided or the key is invalid")
	ErrPaymentRequired      = errors.New("credits have run out")
	ErrInternalServerError  = errors.New("unexpected error occurred")
	ErrUnexpectedStatusCode = errors.New("returned status code did not match expected status code")
)

Functions

func ExplainGRPCError added in v2.3.0

func ExplainGRPCError(err error) string

ExplainGRPCError returns a human-readable explanation for common gRPC status errors returned by GRPCSchema. Returns an empty string for unrecognized errors.

func NormalizeGRPCEndpoint added in v2.3.0

func NormalizeGRPCEndpoint(raw string) (endpoint string, host string, err error)

NormalizeGRPCEndpoint normalizes a raw gRPC endpoint string to host:port form. Accepts grpc:// or https:// URL schemes, bare hostnames (port 443 assumed), and host:port strings. If raw is empty, DefaultGRPCEndpoint is used.

Types

type Account

type Account struct {
	FirstName    string `json:"first_name"`
	LastName     string `json:"last_name"`
	Email        string `json:"email"`
	Organization struct {
		ID       string `json:"id"`
		Name     string `json:"name"`
		Relation string `json:"relation"`
	} `json:"organization"`
	Scopes      []string `json:"scopes"`
	LookupQuota struct {
		Credits  int `json:"credits"`
		ResetsIn int `json:"resets_in"`
	} `json:"lookup_quota"`
}

Account represents the JSON response returned by the Synthient account endpoint.

It groups data into three major sections:

  • Identity: first/last name and email for the authenticated user.
  • Organization: the organization the user belongs to, including its ID, name, and the user's relation to it.
  • LookupQuota: remaining lookup credits and seconds until the quota resets.

Fields and nested structs map 1:1 to the API's JSON payload via struct tags.

Commonly used fields include Account.Email, Organization.Name, and LookupQuota.Credits.

type AnonymizerEvent

type AnonymizerEvent struct {
	RangeStart string `json:"range_start"`
	RangeEnd   string `json:"range_end"`
	Provider   string `json:"provider"`
	Type       string `json:"type"`
	Timestamp  int64  `json:"timestamp"`
}

AnonymizerEvent is a single observation delivered by the anonymizers real-time stream. Anonymizer events describe IP ranges rather than individual addresses.

type Client

type Client struct {
	HttpClient *http.Client
	Token      string
	BaseAPI    url.URL
	BaseFeeds  url.URL
}

Client is a Synthient API client.

It holds the HTTP transport and configuration required to make API and feed requests.

Fields:

  • HttpClient is the underlying HTTP client used for all requests. If nil, the package may fall back to http.DefaultClient (depending on request helpers).
  • Token is the API token used for authentication.
  • BaseAPI is the base URL for JSON API endpoints (e.g. lookups).
  • BaseFeeds is the base URL for feed endpoints that may return large, streamable payloads (e.g. CSV feeds).

func NewClient

func NewClient(token string) Client

NewClient constructs a Client configured for the Synthient v3 API.

The returned client is initialized with:

  • a new *http.Client as the underlying transport,
  • the provided token for authentication, and
  • default base URLs for the JSON API (BaseAPI) and feeds service (BaseFeeds).

If you need custom timeouts, proxies, or transports, modify c.HttpClient after construction. If Synthient endpoints differ for your environment, you may also override BaseAPI and/or BaseFeeds.

Example:

c := synthient.NewClient(os.Getenv("SYNTHIENT_API_KEY"))
c.HttpClient.Timeout = 30 * time.Second

func (*Client) DownloadAnonymizer added in v2.1.0

func (client *Client) DownloadAnonymizer(
	date string,
	hour *int,
	filename string,
	requestOptions *RequestOptions,
) (io.ReadCloser, error)

DownloadAnonymizer downloads an anonymizer feed Parquet snapshot. If filename is non-empty the snapshot is written to that file and the returned reader is nil. If filename is empty the caller receives the raw reader and must close it. The API issues a 307 redirect to a presigned URL; this method follows it automatically.

date accepts "latest" for the most recent hourly snapshot, or a YYYY-MM-DD string for a daily rollup. For a specific hourly within the current UTC day, set hour to a non-nil pointer in the range 0–23.

Example (write to file):

_, err := client.DownloadAnonymizer("latest", nil, "anonymizers.parquet", nil)

Example (stream reader):

r, err := client.DownloadAnonymizer("latest", nil, "", nil)
if err != nil {
	log.Fatal(err)
}
defer r.Close()

func (*Client) DownloadFeedSnapshot

func (client *Client) DownloadFeedSnapshot(
	stream string,
	date string,
	hour *int,
	filename string,
	requestOptions *RequestOptions,
) (io.ReadCloser, error)

DownloadFeedSnapshot downloads a Parquet snapshot and returns a streaming reader for its contents. The API issues a 307 redirect to a presigned URL valid for 24 hours; this method follows the redirect automatically.

stream must be one of: proxies, anonymizers, torrents, honeypot_http, honeypot_https, honeypot_dns, or honeypot_adb.

date accepts "latest" for the most recent hourly snapshot, or a YYYY-MM-DD string for a daily rollup. For a specific hourly within the current UTC day, set hour to a non-nil pointer in the range 0–23.

If filename is non-empty the snapshot is written to that file and the returned reader is nil. If filename is empty the caller receives the raw reader and must close it.

Example (write to file):

hour := 21
_, err := client.DownloadFeedSnapshot("proxies", "2026-05-07", &hour, "proxies.parquet", nil)
if err != nil {
	log.Fatal(err)
}

Example (stream reader):

r, err := client.DownloadFeedSnapshot("proxies", "2026-05-07", nil, "", nil)
if err != nil {
	log.Fatal(err)
}
defer r.Close()

func (*Client) DownloadHeliosHTTP added in v2.1.0

func (client *Client) DownloadHeliosHTTP(
	date string,
	hour *int,
	filename string,
	requestOptions *RequestOptions,
) (io.ReadCloser, error)

DownloadHeliosHTTP downloads a Helios HTTP capture Parquet snapshot. If filename is non-empty the snapshot is written to that file and the returned reader is nil. If filename is empty the caller receives the raw reader and must close it. The API issues a 307 redirect to a presigned URL; this method follows it automatically.

date accepts "latest" for the most recent hourly snapshot, or a YYYY-MM-DD string for a daily rollup. For a specific hourly within the current UTC day, set hour to a non-nil pointer in the range 0–23.

Example (write to file):

_, err := client.DownloadHeliosHTTP("latest", nil, "helios-http.parquet", nil)

Example (stream reader):

r, err := client.DownloadHeliosHTTP("latest", nil, "", nil)
if err != nil {
	log.Fatal(err)
}
defer r.Close()

func (*Client) DownloadHeliosTLS added in v2.1.0

func (client *Client) DownloadHeliosTLS(
	date string,
	hour *int,
	filename string,
	requestOptions *RequestOptions,
) (io.ReadCloser, error)

DownloadHeliosTLS downloads a Helios TLS capture Parquet snapshot. If filename is non-empty the snapshot is written to that file and the returned reader is nil. If filename is empty the caller receives the raw reader and must close it. The API issues a 307 redirect to a presigned URL; this method follows it automatically.

date accepts "latest" for the most recent hourly snapshot, or a YYYY-MM-DD string for a daily rollup. For a specific hourly within the current UTC day, set hour to a non-nil pointer in the range 0–23.

Example (write to file):

_, err := client.DownloadHeliosTLS("latest", nil, "helios-tls.parquet", nil)

Example (stream reader):

r, err := client.DownloadHeliosTLS("latest", nil, "", nil)
if err != nil {
	log.Fatal(err)
}
defer r.Close()

func (*Client) DownloadProxy added in v2.1.0

func (client *Client) DownloadProxy(
	date string,
	hour *int,
	filename string,
	requestOptions *RequestOptions,
) (io.ReadCloser, error)

DownloadProxy downloads a proxy feed Parquet snapshot. If filename is non-empty the snapshot is written to that file and the returned reader is nil. If filename is empty the caller receives the raw reader and must close it. The API issues a 307 redirect to a presigned URL; this method follows it automatically.

date accepts "latest" for the most recent hourly snapshot, or a YYYY-MM-DD string for a daily rollup. For a specific hourly within the current UTC day, set hour to a non-nil pointer in the range 0–23.

Example (write to file):

_, err := client.DownloadProxy("latest", nil, "proxies.parquet", nil)

Example (stream reader):

r, err := client.DownloadProxy("latest", nil, "", nil)
if err != nil {
	log.Fatal(err)
}
defer r.Close()

func (*Client) DownloadTorrent added in v2.1.0

func (client *Client) DownloadTorrent(
	date string,
	hour *int,
	filename string,
	requestOptions *RequestOptions,
) (io.ReadCloser, error)

DownloadTorrent downloads a torrent feed Parquet snapshot. If filename is non-empty the snapshot is written to that file and the returned reader is nil. If filename is empty the caller receives the raw reader and must close it. The API issues a 307 redirect to a presigned URL; this method follows it automatically.

date accepts "latest" for the most recent hourly snapshot, or a YYYY-MM-DD string for a daily rollup. For a specific hourly within the current UTC day, set hour to a non-nil pointer in the range 0–23.

Example (write to file):

_, err := client.DownloadTorrent("latest", nil, "torrents.parquet", nil)

Example (stream reader):

r, err := client.DownloadTorrent("latest", nil, "", nil)
if err != nil {
	log.Fatal(err)
}
defer r.Close()

func (*Client) FeedSnapshotMeta

func (client *Client) FeedSnapshotMeta(
	stream string,
	date string,
	requestOptions *RequestOptions,
) (FeedSnapshotMeta, error)

FeedSnapshotMeta returns JSON metadata for a single Parquet snapshot, including its SHA-256 checksum, byte size, row count, parquet schema, and canonical date.

stream must be one of: proxies, anonymizers, torrents, honeypot_http, honeypot_https, honeypot_dns, or honeypot_adb.

date is the snapshot identifier: YYYY-MM-DD for daily rollups, YYYY-MM-DD/HH for past hourlies, or "latest" for the most recent hourly snapshot.

Example:

meta, err := client.FeedSnapshotMeta("proxies", "latest", nil)
if err != nil {
	log.Fatal(err)
}
fmt.Printf("rows=%d checksum=%s\n", meta.Rows, meta.Checksum)

func (*Client) FeedSnapshots

func (client *Client) FeedSnapshots(
	stream string,
	options *FeedSnapshotsOptions,
	requestOptions *RequestOptions,
) (FeedSnapshotsPage, error)

FeedSnapshots returns one page of available daily and hourly Parquet snapshots for the given stream. Pages are ordered newest-first and capped at 500 rows by the API.

stream must be one of: proxies, anonymizers, torrents, honeypot_http, honeypot_https, honeypot_dns, or honeypot_adb.

Pass FeedSnapshotsPage.NextCursor back via opts.Cursor to fetch the next page. NextCursor is empty on the final page.

Example:

page, err := client.FeedSnapshots("proxies", &synthient.FeedSnapshotsOptions{Limit: 50}, nil)
if err != nil {
	log.Fatal(err)
}
for _, snap := range page.Feeds {
	fmt.Printf("%s %s %d bytes\n", snap.Kind, snap.ID, snap.SizeBytes)
}

func (*Client) GRPCSchema added in v2.3.0

func (client *Client) GRPCSchema(ctx context.Context, options *GRPCSchemaOptions) (GRPCSchemaResult, error)

GRPCSchema uses gRPC server reflection to fetch protobuf file descriptors from a Synthient gRPC endpoint. If options is nil or options.Endpoint is empty, it connects to DefaultGRPCEndpoint. If options.Symbols is empty, all services exposed by the server are fetched.

The client's token is forwarded as the x-api-key metadata header when non-empty.

Example (all services):

result, err := client.GRPCSchema(ctx, nil)
if err != nil {
	log.Fatal(err)
}
for _, f := range result.DescriptorSet.File {
	fmt.Printf("%s  %s\n", f.GetName(), f.GetPackage())
}

Example (specific symbol):

result, err := client.GRPCSchema(ctx, &synthient.GRPCSchemaOptions{
	Symbols: []string{"synthient.lookup.v1.LookupService"},
})

func (*Client) GetAccount

func (client *Client) GetAccount(options *RequestOptions) (Account, error)

GetAccount retrieves profile and quota details for the authenticated user.

It performs an HTTP GET request to the Synthient account endpoint and unmarshals the JSON response into an Account value. The request is expected to return http.StatusOK; non-OK responses are returned as errors.

options can be used to customize request behavior (timeouts, headers, etc.).

Example:

account, err := client.GetAccount(nil)
if err != nil {
	log.Fatal(err)
}
fmt.Printf("%+v\n", account)

func (*Client) GetDomain

func (client *Client) GetDomain(domain string, options *RequestOptions) (Domain, error)

func (*Client) GetIP

func (client *Client) GetIP(ip string, options *RequestOptions) (IP, error)

GetIP looks up enrichment data for a single IP address.

It performs an HTTP GET request to the Synthient IP lookup endpoint and unmarshals the JSON response into an IP value. The request is expected to return http.StatusOK; non-OK responses are returned as errors.

options can be used to customize request behavior (timeouts, headers, etc.).

Example:

info, err := client.GetIP("8.8.8.8", nil)
if err != nil {
	log.Fatal(err)
}
fmt.Printf("%+v\n", info)

func (*Client) GetIPs

func (client *Client) GetIPs(ips []string, options *RequestOptions) ([]IP, error)

GetIPs looks up enrichment data for multiple IP addresses in a single request.

It performs an HTTP POST request to the Synthient bulk IP lookup endpoint, sending the provided IPs as a JSON body, and returns the results in the same order as the input slice. The request is expected to return http.StatusOK; non-OK responses are returned as errors.

options can be used to customize request behavior (timeouts, headers, etc.).

Example:

results, err := client.GetIPs([]string{"8.8.8.8", "1.1.1.1"}, nil)
if err != nil {
	log.Fatal(err)
}
for _, info := range results {
	fmt.Printf("%s: risk=%d\n", info.IP, info.Intelligence.RiskScore)
}

func (*Client) StreamAnonymizer

func (client *Client) StreamAnonymizer(requestOptions *RequestOptions) iter.Seq2[AnonymizerEvent, error]

StreamAnonymizer connects to the real-time anonymizer stream and returns an iterator that yields one AnonymizerEvent per newline-delimited JSON event. Events describe IP ranges (VPNs, Tor exits, relay-class detections) rather than individual addresses. The stream runs until the connection is closed, the context in requestOptions is cancelled, or a decode error occurs.

Example:

for event, err := range client.StreamAnonymizer(nil) {
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s-%s %s %s\n", event.RangeStart, event.RangeEnd, event.Type, event.Provider)
}

func (*Client) StreamHeliosHTTP

func (client *Client) StreamHeliosHTTP(
	requestOptions *RequestOptions,
) iter.Seq2[HeliosHTTPEvent, error]

StreamHeliosHTTP connects to the real-time Helios HTTP capture stream and returns an iterator that yields one HeliosHTTPEvent per newline-delimited JSON event. Each event includes the HTTP method, URI, headers, raw request bytes, and source metadata. The stream runs until the connection is closed, the context in requestOptions is cancelled, or a decode error occurs.

Example:

for event, err := range client.StreamHeliosHTTP(nil) {
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s %s %s\n", event.Details.Method, event.Details.URI, event.Domain)
}

func (*Client) StreamHeliosTLS

func (client *Client) StreamHeliosTLS(
	requestOptions *RequestOptions,
) iter.Seq2[HeliosTLSEvent, error]

StreamHeliosTLS connects to the real-time Helios TLS capture stream and returns an iterator that yields one HeliosTLSEvent per newline-delimited JSON event. Each event carries the fully parsed TLS ClientHello including cipher suites, extensions, supported groups, signature algorithms, and handshake flags. Details is nil when parsing failed. The stream runs until the connection is closed, the context in requestOptions is cancelled, or a decode error occurs.

Example:

for event, err := range client.StreamHeliosTLS(nil) {
	if err != nil {
		log.Fatal(err)
	}
	if event.Details != nil {
		fmt.Printf("%s  %s  suites=%d\n", event.Domain, event.Details.HandshakeVersion,

len(event.Details.CipherSuites))

	}
}

func (*Client) StreamProxy

func (client *Client) StreamProxy(requestOptions *RequestOptions) iter.Seq2[ProxyEvent, error]

StreamProxy connects to the real-time proxy stream and returns an iterator that yields one ProxyEvent per newline-delimited JSON event. The stream runs until the connection is closed, the context in requestOptions is cancelled, or a decode error occurs.

Example:

for event, err := range client.StreamProxy(nil) {
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s %s %s\n", event.IP, event.Provider, event.CountryCode)
}

func (*Client) StreamTorrent

func (client *Client) StreamTorrent(requestOptions *RequestOptions) iter.Seq2[TorrentEvent, error]

StreamTorrent connects to the real-time torrent stream and returns an iterator that yields one TorrentEvent per newline-delimited JSON event. Each event includes the info hash, metadata, per-file details, and observed peers from DHT, PEX, or trackers. The stream runs until the connection is closed, the context in requestOptions is cancelled, or a decode error occurs.

Example:

for event, err := range client.StreamTorrent(nil) {
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s %s %d peers\n", event.InfoHash, event.Name, len(event.Peers))
}

type Domain

type Domain struct {
	Domain string `json:"domain"`
	Status string `json:"status"`
	Stats  struct {
		Events24H      int `json:"events_24h"`
		TotalEvents30D int `json:"total_events_30d"`
	} `json:"stats"`
	TimeSeries []struct {
		Date      int `json:"date"`
		Events    int `json:"events"`
		UniqueIPs int `json:"unique_ips"`
	} `json:"time_series"`
	UniqueIPs struct {
		Value24H     int   `json:"value_24h"`
		Value30D     int   `json:"value_30d"`
		Sparkline24H []int `json:"sparkline_24h"`
	} `json:"unique_ips"`
	TopASN struct {
		ASN    int `json:"asn"`
		Events int `json:"events"`
	} `json:"top_asn"`
	TopSubdomains []struct {
		Subdomain string `json:"subdomain"`
		Count     int    `json:"count"`
	} `json:"top_subdomains"`
	TopPorts []struct {
		Port  int `json:"port"`
		Count int `json:"count"`
	} `json:"top_ports"`
	GeoDistribution []struct {
		CountryCode string `json:"country_code"`
		UniqueIPs   int    `json:"unique_ips"`
		Events      int    `json:"events"`
	} `json:"geo_distribution"`
	HourDowHeatmap [][]int `json:"hour_dow_heatmap"`
	ActivityStats  struct {
		PeakHour      int    `json:"peak_hour"`
		QuietHour     int    `json:"quiet_hour"`
		MedianPerHour int    `json:"median_per_hour"`
		P95PerHour    int    `json:"p95_per_hour"`
		Cadence       string `json:"cadence"`
	} `json:"activity_stats"`
	RecentEvents []struct {
		Timestamp       int    `json:"timestamp"`
		SourceIPMasked  string `json:"source_ip_masked"`
		TargetSubdomain string `json:"target_subdomain"`
		Port            int    `json:"port"`
		CountryCode     string `json:"country_code"`
	} `json:"recent_events"`
}

type FeedSnapshot

type FeedSnapshot struct {
	Kind         string `json:"kind"`
	Date         string `json:"date"`
	Hour         *int   `json:"hour,omitempty"`
	SizeBytes    int64  `json:"size_bytes"`
	RowCount     int64  `json:"row_count"`
	Checksum     string `json:"checksum"`
	ID           string `json:"id"`
	CreatedAt    int64  `json:"created_at"`
	DownloadPath string `json:"download_path"`
}

FeedSnapshot represents a single Parquet snapshot entry returned by the feeds export endpoint.

type FeedSnapshotMeta

type FeedSnapshotMeta struct {
	Stream    string `json:"stream"`
	Kind      string `json:"kind"`
	Hour      *int   `json:"hour,omitempty"`
	ID        string `json:"id"`
	Format    string `json:"format"`
	Date      int64  `json:"date"`
	CreatedAt int64  `json:"created_at"`
	Size      int64  `json:"size"`
	Rows      int64  `json:"rows"`
	Checksum  string `json:"checksum"`
	Schema    struct {
		Fields []struct {
			Name string `json:"name"`
			Type string `json:"type"`
		} `json:"fields"`
	} `json:"schema"`
}

FeedSnapshotMeta holds the metadata returned for a single Parquet snapshot.

type FeedSnapshotsOptions

type FeedSnapshotsOptions struct {
	// Limit is the page size. Defaults to 100; values above 500 are clamped by the API.
	Limit int
	// Cursor is the opaque pagination token from the previous page's NextCursor field.
	// Leave empty on the first call.
	Cursor string
}

FeedSnapshotsOptions controls pagination for the FeedSnapshots call.

type FeedSnapshotsPage

type FeedSnapshotsPage struct {
	Stream     string         `json:"stream"`
	Feeds      []FeedSnapshot `json:"feeds"`
	NextCursor string         `json:"next_cursor"`
}

FeedSnapshotsPage is a single page of results from FeedSnapshots.

type GRPCSchemaOptions added in v2.3.0

type GRPCSchemaOptions struct {
	// Endpoint is the gRPC server address (host:port or grpc://host:port).
	// Defaults to DefaultGRPCEndpoint when empty.
	Endpoint string
	// Plaintext disables TLS. Useful for local development against a plaintext server.
	Plaintext bool
	// IncludeReflection includes the gRPC reflection service itself in the output.
	IncludeReflection bool
	// Symbols is the list of fully-qualified service or message names to resolve.
	// When empty, all services exposed by the server are fetched.
	Symbols []string
}

GRPCSchemaOptions configures a GRPCSchema call.

type GRPCSchemaResult added in v2.3.0

type GRPCSchemaResult struct {
	// Endpoint is the normalized gRPC address that was queried.
	Endpoint string
	// Symbols lists the service symbols that were resolved.
	Symbols []string
	// DescriptorSet contains all resolved protobuf file descriptors in topological
	// dependency order.
	DescriptorSet *descriptorpb.FileDescriptorSet
}

GRPCSchemaResult holds the output of a GRPCSchema call.

type HeliosHTTPEvent

type HeliosHTTPEvent struct {
	Timestamp int64  `json:"timestamp"`
	Domain    string `json:"domain"`
	Port      int    `json:"port"`
	TunnelID  int64  `json:"tunnel_id"`
	Protocol  string `json:"protocol"`
	Details   struct {
		Method  string            `json:"method"`
		URI     string            `json:"uri"`
		Version string            `json:"version"`
		Headers map[string]string `json:"headers"`
	} `json:"details"`
	Raw  string `json:"raw"`
	Meta struct {
		PoolID   string `json:"pool_id"`
		Provider string `json:"provider"`
		ProxyIP  string `json:"proxy_ip"`
		Server   string `json:"server"`
	} `json:"meta"`
}

HeliosHTTPEvent is a single HTTP capture delivered by the Helios HTTP sensor stream.

type HeliosTLSDetails

type HeliosTLSDetails struct {
	RecordVersion    string `json:"record_version"`
	HandshakeVersion string `json:"handshake_version"`
	ClientRandom     string `json:"client_random"`
	SessionID        string `json:"session_id"`
	SessionIDLength  int    `json:"session_id_length"`
	CipherSuites     []struct {
		Code int    `json:"code"`
		Name string `json:"name"`
	} `json:"cipher_suites"`
	CompressionMethods []int    `json:"compression_methods"`
	SNI                string   `json:"sni"`
	SupportedVersions  []string `json:"supported_versions"`
	SupportedGroups    []struct {
		Code int    `json:"code"`
		Name string `json:"name"`
	} `json:"supported_groups"`
	ECPointFormats      []string `json:"ec_point_formats"`
	SignatureAlgorithms []struct {
		Code int    `json:"code"`
		Name string `json:"name"`
	} `json:"signature_algorithms"`
	Extensions []struct {
		Code   int    `json:"code"`
		Name   string `json:"name"`
		Length int    `json:"length"`
	} `json:"extensions"`
	KeyShareGroups      []string `json:"key_share_groups"`
	PSKKeyExchangeModes []string `json:"psk_key_exchange_modes"`

	ExtendedMasterSecret        bool `json:"extended_master_secret"`
	RenegotiationInfo           bool `json:"renegotiation_info"`
	StatusRequest               bool `json:"status_request"`
	SignedCertificateTimestamps bool `json:"signed_certificate_timestamps"`
	HasGREASE                   bool `json:"has_grease"`
	EncryptThenMAC              bool `json:"encrypt_then_mac"`
	PostHandshakeAuth           bool `json:"post_handshake_auth"`
	DelegatedCredentials        bool `json:"delegated_credentials"`
	ApplicationSettings         bool `json:"application_settings"`
}

HeliosTLSDetails holds the parsed TLS ClientHello from a Helios TLS capture event. It is nil when the sensor was unable to parse the handshake record.

type HeliosTLSEvent

type HeliosTLSEvent struct {
	Timestamp int64  `json:"timestamp"`
	Domain    string `json:"domain"`
	Port      int    `json:"port"`
	TunnelID  int64  `json:"tunnel_id"`
	Protocol  string `json:"protocol"`
	Meta      struct {
		PoolID   string `json:"pool_id"`
		Provider string `json:"provider"`
		ProxyIP  string `json:"proxy_ip"`
		Server   string `json:"server"`
	} `json:"meta"`
	Details *HeliosTLSDetails `json:"details"`
}

HeliosTLSEvent is a single TLS ClientHello capture delivered by the Helios HTTPS sensor stream.

type IP

type IP struct {
	IP      string `json:"ip"`
	Network struct {
		Asn        int    `json:"asn"`
		Isp        string `json:"isp"`
		Type       string `json:"type"`
		Org        string `json:"org"`
		AbuseEmail string `json:"abuse_email"`
		AbusePhone string `json:"abuse_phone"`
		Domain     string `json:"domain"`
	} `json:"network"`
	Location struct {
		Country   string  `json:"country"`
		State     string  `json:"state"`
		City      string  `json:"city"`
		Timezone  string  `json:"timezone"`
		Longitude float64 `json:"longitude"`
		Latitude  float64 `json:"latitude"`
		GeoHash   string  `json:"geo_hash"`
	} `json:"location"`
	Intelligence struct {
		RiskScore  int      `json:"risk_score"`
		Behavior   []string `json:"behavior"`
		Categories []string `json:"categories"`
		Devices    []struct {
			OS      string `json:"os"`
			Version string `json:"version"`
		} `json:"devices"`
		Providers []struct {
			Provider string `json:"provider"`
			Type     string `json:"type"`
			LastSeen int64  `json:"last_seen"`
		} `json:"providers"`
	} `json:"intelligence"`
}

IP represents the JSON response returned by the Synthient IP lookup endpoint.

It groups data into three major sections:

  • Network: ASN/ISP and ownership/abuse contacts for the IP’s network.
  • Location: coarse geolocation attributes associated with the IP.
  • IPData: device/behavior/category/enrichment signals and an overall risk score.

Fields and nested structs map 1:1 to the API’s JSON payload via struct tags. Note that values (especially geolocation and “risk”) are provider-derived and may be approximate.

Commonly used fields include IP.IP, Network.Asn/Network.Isp, Location.Country, and IPData.IPRisk.

type ProxyEvent

type ProxyEvent struct {
	IP          string `json:"ip"`
	Provider    string `json:"provider"`
	Type        string `json:"type"`
	Timestamp   int64  `json:"timestamp"`
	CountryCode string `json:"country_code"`
	ASN         int    `json:"asn"`
}

ProxyEvent is a single observation delivered by the proxies real-time stream.

type RequestOptions

type RequestOptions struct {
	Context context.Context
}

RequestOptions configures optional per-request behavior for client calls.

It is passed to request helpers and API methods to override defaults without changing the Client itself. When Context is non-nil, it is used for request cancellation, deadlines, and timeouts. If Context is nil, the request uses context.Background() (or the client/request default).

type TorrentEvent

type TorrentEvent struct {
	InfoHash    string `json:"info_hash"`
	Name        string `json:"name"`
	MagnetURI   string `json:"magnet_uri"`
	TotalSize   int64  `json:"total_size"`
	PieceLength int64  `json:"piece_length"`
	FileCount   int    `json:"file_count"`
	Files       []struct {
		Path   string `json:"path"`
		Length int64  `json:"length"`
	} `json:"files"`
	Peers []struct {
		IP        string `json:"ip"`
		Port      int    `json:"port"`
		Source    string `json:"source"`
		Encrypted bool   `json:"encrypted"`
	} `json:"peers"`
	Timestamp int64 `json:"timestamp"`
}

TorrentEvent is a single observation delivered by the torrents real-time stream.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL