Skip to main content
This endpoint requires access to Account & Session Takeover Prevention (ASTP). Please contact your Customer Success Manager for more details.
Flare’s Leaked Credentials API can be used to export a domain’s leaked credentials. This guide will explain how to export all leaked credentials for the example.com domain using the credentials/_search endpoint.

Export Steps

1

Fetch one page of results

Use the credentials/_search endpoint to fetch one page of results.If the returned page of results is empty, this means that the export is complete.
2

Print the results

Loop over the response’s items and print the results.
3

Ratelimit and go to step 1

Wait one second to avoid going over the API rate limit. Then, go back to step 1 to fetch the next page.

End-to-End Examples

These are end-to-end examples in various programming languages.
import csv
import sys
import time

from flareio import FlareApiClient


api_client = FlareApiClient.from_env()

# The cursor from which we are starting the current execution.
last_from: str | None = None

writer = csv.DictWriter(
    sys.stdout,
    fieldnames=[
        "identity",
        "password",
        "source",
    ],
)

for resp in api_client.scroll(
    method="POST",
    url="/astp/v2/credentials/_search",
    json={
        "query": {
            "type": "domain",
            "fqdn": "scatterholt.com",
        },
        "from": last_from,
    },
):
    # Print results
    credentials = resp.json()["items"]
    for credential in credentials:
        writer.writerow(
            {
                "identity": credential["identity_name"],
                "password": credential["hash"],
                "source": credential["source"]["id"],
            },
        )

    # Save the cursor for the next execution
    last_from = resp.json().get("next") or last_from

    # Rate limiting.
    time.sleep(0.25)

print(f"The next execution could resume using {last_from=}.")
package main

import (
	"encoding/csv"
	"encoding/json"
	"fmt"
	"os"
	"strconv"
	"time"

	"github.com/Flared/go-flareio"
)

type CredentialsResponse struct {
	Items []Credential `json:"items"`
}

type CredentialSource struct {
	Id string `json:"id"`
}

type Credential struct {
	Id           int               `json:"id"`
	Source       *CredentialSource `json:"source"`
	IdentityName string            `json:"identity_name"`
	Hash         string            `json:"hash"`
}

func exportDomainCredentials(
	client *flareio.ApiClient,
	domain string,
) error {
	csvWriter := csv.NewWriter(os.Stdout)

	for result, err := range client.IterPostJson(
		"/astp/v2/credentials/_search",
		nil,
		map[string]interface{}{
			"query": map[string]string{
				"type": "domain",
				"fqdn": domain,
			},
		},
	) {
		// Rate Limiting
		time.Sleep(time.Second * 1)

		if err != nil {
			return fmt.Errorf("failed to fetch page: %w", err)
		}

		var credentialsResponse CredentialsResponse
		if err := json.NewDecoder(result.Response.Body).Decode(&credentialsResponse); err != nil {
			return fmt.Errorf("failed to decode response: %w", err)
		}

		for _, credential := range credentialsResponse.Items {
			if err := csvWriter.Write(
				[]string{
					strconv.Itoa(credential.Id),
					credential.Source.Id,
					credential.IdentityName,
					credential.Hash,
				},
			); err != nil {
				return fmt.Errorf("failed to output record: %w", err)
			}
		}

		csvWriter.Flush()
		if err := csvWriter.Error(); err != nil {
			return fmt.Errorf("failed to flush writer: %w", err)
		}

		if err := result.Response.Body.Close(); err != nil {
			return fmt.Errorf("failed to close response: %w", err)
		}
	}

	return nil
}

func main() {
	client := flareio.NewApiClient(
		os.Getenv("FLARE_API_KEY"),
	)
	if err := exportDomainCredentials(client, "scatterholt.com"); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}
I