> ## Documentation Index
> Fetch the complete documentation index at: https://wiki.darknetsearch.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Filtered credentials

> Clean, deduplicated, domain-scoped credentials for the domains you own — scored and arranged by category.

Filtered credentials is the cleaned-up, domain-scoped view of your leaked accounts. It reads the same underlying leak data as [Raw Data](/api/guides/credentials-raw-sweep), then **deduplicates** it, **scores** every account, and lets you **arrange** the results by category. Where Raw Data hands you every record to work through yourself, this hands you a deduplicated account list built around a domain you own.

<Warning>
  **Built for the domains you own.** This summarizes the accounts on a domain like `acme.com`. Two limits — both enforced when you create the search — keep you from pointing it at the wrong target:

  * **High-volume public domains are blocked.** Free-mail and consumer providers (`gmail.com`, `outlook.com`, `yahoo.com`, and roughly a thousand others) are on a block list. A search against one fails with a message that the domain *"cannot be searched directly … known to contain an extremely large number of leaked records."*
  * **There's a 5,000,000-record ceiling.** Any other domain whose total leaked-record count tops 5,000,000 is turned away the same way, with a message naming the count and the limit. Contact support to enable a specific domain.

  To investigate a single address on a public domain — say `jdoe@gmail.com` — search the account index directly with [`accounts_database_search`](/api/guides/credentials-ulp-feed) instead, which has no domain restriction.
</Warning>

<Note>
  **Want the machine, not the account?** Filtered credentials hands you a deduplicated account list. Its organization-scoped sibling, [Stealer logs](/api/guides/credentials-stealer-logs), searches the same corpus by *infected device* — when an exposure traces to info-stealer malware and you need the whole capture (session cookies, screenshots, everything else that was on the machine), start there.
</Note>

### Run a search

A filtered search is a four-step async flow: see which filters exist, submit the search, poll until it's ready, then read the accounts.

<Steps>
  <Step title="See the filters">
    Start here. [`leak_filter_filters`](https://client-api.leak.center/scalar-docs/#tag/leak-filter/GET/service/leak_filter_filters/) returns the live catalog — each filter's `id`, `name`, `description`, and `parameters_schema`. It's the source of truth for the IDs below, since the catalog is configured per environment. The `filter_id` you pick is the **arrangement**: it decides which slice of your exposed accounts comes back, and whether you need to supply any `filter_parameters`.

    | Filter (`filter_id`)                       | Isolates                                                                                                                                                                                  | Needs                                           |
    | ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- |
    | Unique Credentials (`5`, default)          | Every deduplicated account for the domain                                                                                                                                                 | —                                               |
    | Unique Domain Accounts (`8`)               | Currently returns the same deduplicated set as Unique Credentials (`5`) — the username + password-only dedup is not yet applied, so don't rely on it for a distinct "unique logins" count | —                                               |
    | Employee Logins on External Services (`2`) | Accounts on services *outside* your own domain                                                                                                                                            | —                                               |
    | Employee Private Activity (`3`)            | Accounts on personal-life services — streaming, social, gambling, dating, crypto, adult, piracy, VPNs                                                                                     | —                                               |
    | Own Infrastructure Credentials (`6`)       | Logins **to your own servers** by your own people (internal / own-domain usernames)                                                                                                       | —                                               |
    | Third Party Logins (`7`)                   | Logins **to your own servers** by outsiders — clients, partners, vendors (external-email usernames)                                                                                       | —                                               |
    | Include Usernames (`1`)                    | Only accounts whose username contains a term you give                                                                                                                                     | `filter_parameters: {"usernames": "alice,bob"}` |
    | Exclude Usernames (`4`)                    | Drops accounts whose username contains a term you give                                                                                                                                    | `filter_parameters: {"usernames": "alice,bob"}` |
    | Exclude Systems (`9`)                      | Drops accounts whose server contains a term you give                                                                                                                                      | `filter_parameters: {"systems": "vpn,mail"}`    |

    The Include/Exclude filters match a **case-insensitive substring** (so `alice` also matches `alice.smith`), and take comma-separated values.
  </Step>

  <Step title="Create the search">
    [`leak_filter_search_create`](https://client-api.leak.center/scalar-docs/#tag/leak-filter/POST/service/leak_filter_search_create/) submits it. Pass the domain, the `filter_id`, and `mode`. Use `soft_wait`: it returns a task to poll and still gives you results when only part of the data finished in time. (`hard_wait` is all-or-nothing — it reaches `ready` only once collection and analysis both fully complete, and fails otherwise.) It comes back with an `id` and a `status`.

    ```bash theme={"dark"}
    curl https://client-api.leak.center/api/service/leak_filter_search_create/ \
      -X POST \
      -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"domain_url": "acme.com", "filter_id": 5, "mode": "soft_wait"}'
    ```

    Narrow to one or more usernames with Include Usernames (`filter_id` 1), passing them in `filter_parameters` (the key is plural — `usernames`):

    ```bash theme={"dark"}
      -d '{"domain_url": "acme.com", "filter_id": 1, "mode": "soft_wait", "filter_parameters": {"usernames": "jdoe"}}'
    ```

    Or surface employee accounts on personal-life services with Employee Private Activity (`filter_id` 3):

    ```bash theme={"dark"}
      -d '{"domain_url": "acme.com", "filter_id": 3, "mode": "soft_wait"}'
    ```
  </Step>

  <Step title="Poll until it's ready">
    Fetch the task with [`leak_filter_search_retrieve`](https://client-api.leak.center/scalar-docs/#tag/leak-filter/GET/service/leak_filter_search_retrieve/), passing the `id` from the previous step as `filter_task_id`, until its `status` reads `ready` (or `incomplete_ready`).

    ```bash theme={"dark"}
    curl "https://client-api.leak.center/api/service/leak_filter_search_retrieve/?filter_task_id=12345" \
      -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
    ```

    The **first** search for a domain is the heavy one. The platform walks every leak exposing that domain — back to 2020 — deduplicates it, and scores each account. It runs asynchronously, so depending on how much data is exposed (and how busy the queue is) it can take many minutes, sometimes up to around 20. Poll about every 30 seconds; status moves `pending` → `in_progress` → `ready`. A status of `incomplete_ready` is also usable — it means results are available but built from a partial run.

    After that first run, the results are stored as deduplicated account rows. Every later search for the same domain only processes the **delta** — the new leaks since last time — so it comes back far faster.
  </Step>

  <Step title="Read the accounts">
    Fetch the results with [`leak_filter_search_results`](https://client-api.leak.center/scalar-docs/#tag/leak-filter/GET/service/leak_filter_search_results/), again by `filter_task_id`. Results are paginated (`count`, `next`, `previous`, `results`).

    ```bash theme={"dark"}
    curl "https://client-api.leak.center/api/service/leak_filter_search_results/?filter_task_id=12345" \
      -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
    ```
  </Step>
</Steps>

**Reading an already-searched domain.** Once a domain has been searched at least once, its results stay stored — so you can read them straight from the domain, with no `filter_task_id` to track. [`leak_filter_domain_search_results`](https://client-api.leak.center/scalar-docs/#tag/leak-filter/GET/service/leak_filter_domain_search_results/) takes `domain_url` + `filter_id` and returns the current accounts directly. It's what the dashboard's Credentials view uses — and it only works for a domain that already has a search behind it: call it for one that's never been searched and you get a `404` (*"No results available. The requested domain does not exist."*). So run the flow above first.

```bash theme={"dark"}
curl "https://client-api.leak.center/api/service/leak_filter_domain_search_results/?domain_url=acme.com&filter_id=5" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

### What comes back

Each account row carries the credential, where it was used, when it surfaced, and how it scores:

* the credential — `server`, `username`, `password`
* classification — `is_infrastructure`, `is_business`, `is_private`, `has_url`
* scoring — `risk_score`, `novelty_score`, `reuse_count_till_creation_time`, `first_discovery`
* provenance — `leaks` (each with `leak_id` and `leak_name`), `leak_publish_date`, `leak_discover_date`, `tags`

**The list is already deduplicated.** The platform stores one row per `server` + `username` + `password`, so the same login on a *different* server stays a separate row — it's a different exposure to act on. The default arrangement, Unique Credentials (`filter_id` 5), returns that full deduplicated set; the other filters narrow it.

**Ordering.** Sort with `order` and `direction` (`asc` or `desc`). The API defaults to `created_at` descending; the dashboard's Credentials view sorts by `novelty_score` descending.

| `order`                          | What it ranks by                                                                                                                              |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `novelty_score`                  | Freshness — a 0–10 score; newer, less-reused credentials rank higher (computed below).                                                        |
| `risk_score`                     | A 0–10 priority score blending novelty with exposure signals (computed below).                                                                |
| `first_discovery`                | The date this exact credential was first seen anywhere in the corpus.                                                                         |
| `reuse_count_till_creation_time` | How many earlier records already held the same username + password — a high count means the pair was circulating widely before this sighting. |
| `created_at`                     | When DarknetSearch indexed this particular record.                                                                                            |

### How novelty and risk are scored

`novelty_score` and `risk_score` are **computed**, not pulled from the leak. Both run `0`–`10`.

**Novelty — how fresh a credential is.** It's the average of two sub-scores.

Recency, from when the credential was first seen:

| First seen    | Points |
| ------------- | ------ |
| ≤ 1 month ago | 10     |
| ≤ 6 months    | 8      |
| ≤ 12 months   | 6      |
| ≤ 24 months   | 4      |
| older         | 2      |

Reuse, from how many earlier records already carried the same username + password:

| Prior sightings | Points |
| --------------- | ------ |
| 0               | 10     |
| 1–4             | 7      |
| 5–9             | 4      |
| 10 or more      | 1      |

A brand-new, never-seen credential scores 10; an old, heavily recycled one bottoms out near 2. By default the two sub-scores are weighted equally — the `first_discovery_weight` and `reuse_weight` settings below re-balance them.

**Risk — how urgently it deserves attention.** A weighted average of four inputs, each normalized to `0`–`1`, then scaled back to `0`–`10`:

| Input               | Value                                             | Default weight |
| ------------------- | ------------------------------------------------- | -------------- |
| Novelty             | the novelty score above, ÷ 10                     | 3              |
| `has_url`           | 1 if a real server/URL was captured, else 0       | 1              |
| `is_infrastructure` | 1 if the login is tied to your own infrastructure | 2              |
| `is_business`       | 1 if the source leak is tagged business           | 1              |

```
# with the default weights (total = 7), capped at 10
risk = round( (3*(novelty/10) + 1*has_url + 2*is_infrastructure + 1*is_business) / 7 * 10 )
```

So a fresh credential on your own infrastructure scores highest; an old personal-service login scores lowest. `is_private` is recorded on the row but does **not** affect the score.

**Tuning the weights.** All six weights are org-level and tunable `0`–`5`: `first_discovery_weight` and `reuse_weight` shape the novelty score; `novelty_weight`, `url_presence_weight`, `infrastructure_weight`, and `business_weight` shape the risk score (defaults `3`, `1`, `2`, `1`). Read them with [`leak_filter_risk_settings_retrieve`](https://client-api.leak.center/scalar-docs/#tag/leak-filter/GET/service/leak_filter_risk_settings_retrieve/) and change them with [`leak_filter_risk_settings_update`](https://client-api.leak.center/scalar-docs/#tag/leak-filter/PUT/service/leak_filter_risk_settings_update/); scores re-compute on the next read.

### Match against your password policy

A leaked password that still satisfies your **current** password policy is the dangerous kind: it's plausibly still in use, so it may still open the account it was taken from. Filtered credentials can flag exactly those — define a policy once, then apply it to any search.

**Define it.** A password policy is a standalone, org-scoped object. Create one with [`leak_filter_password_policies_create`](https://client-api.leak.center/scalar-docs/#tag/leak-filter/POST/service/leak_filter_password_policies_create/):

```bash theme={"dark"}
curl https://client-api.leak.center/api/service/leak_filter_password_policies_create/ \
  -X POST \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Corporate 2026", "min_length": 12, "require_numbers": true, "require_special_chars": true, "require_uppercase": true}'
```

A policy is a minimum length plus up to three character-class requirements: `min_length` (default `8`), `require_numbers`, `require_special_chars`, and `require_uppercase` (all default `false`). A password **matches** when it clears `min_length` and each requirement you turned on — at least one digit, at least one `A`–`Z`, and at least one of `!@#$%^&*(),.?":{}|<>`. Manage policies with [`leak_filter_password_policies_list`](https://client-api.leak.center/scalar-docs/#tag/leak-filter/GET/service/leak_filter_password_policies_list/), [`leak_filter_password_policy_retrieve`](https://client-api.leak.center/scalar-docs/#tag/leak-filter/GET/service/leak_filter_password_policy_retrieve/\{policy_id}/), [`leak_filter_password_policy_update`](https://client-api.leak.center/scalar-docs/#tag/leak-filter/PUT/service/leak_filter_password_policy_update/\{policy_id}/), and [`leak_filter_password_policy_delete`](https://client-api.leak.center/scalar-docs/#tag/leak-filter/DELETE/service/leak_filter_password_policy_delete/\{policy_id}/).

**Apply it.** Pass `pwd_policy_ids` (comma-separated) on the results call:

```bash theme={"dark"}
curl "https://client-api.leak.center/api/service/leak_filter_domain_search_results/?domain_url=acme.com&filter_id=5&pwd_policy_ids=3" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```

This adds a `matches_password_policy` boolean to every row. It **tags, it doesn't filter** — non-matching accounts still come back, so you keep the full picture and can sort or triage by the flag. (Pass several IDs and a row is flagged if it matches *any* of them.)

<Warning>
  **Treat a match as a live-credential signal.** `matches_password_policy: true` means the leaked password would still pass your policy today — so it may still be a working credential into the very server the leak names. Prioritize those accounts for rotation ahead of the rest.
</Warning>

### Export the results

To pull a full result set in one file rather than paging, use an **export** — an asynchronous job. Filtered credentials has dedicated leak-filter export endpoints; for the general export pattern across other result sets, see [Downloads and exports](/api/guides/downloads-exports). (The old direct-download endpoints have been removed in favour of this flow.)

<Steps>
  <Step title="Create the export">
    Create it from a completed filter task with [`leak_filter_export_create_from_filter_task`](https://client-api.leak.center/scalar-docs/#tag/leak-filter/POST/service/leak_filter_export_create_from_filter_task/) (pass `filter_task_id`), or straight from a stored domain with [`leak_filter_export_create_from_domain`](https://client-api.leak.center/scalar-docs/#tag/leak-filter/POST/service/leak_filter_export_create_from_domain/) (pass `domain_url` + `filter_id`). Each returns an export `id` and `status`.
  </Step>

  <Step title="Poll until ready">
    Poll [`leak_filter_export_retrieve`](https://client-api.leak.center/scalar-docs/#tag/leak-filter/GET/service/leak_filter_export_retrieve/\{id}/) with the export `id` until `status` is `ready`.
  </Step>

  <Step title="Download">
    Fetch the file from [`leak_filter_export_download`](https://client-api.leak.center/scalar-docs/#tag/leak-filter/GET/service/leak_filter_export_download/\{id}/). **The link expires 24 hours after creation** — a later download returns `410 Gone`, so create a fresh export if you need it again. [`leak_filter_export_list`](https://client-api.leak.center/scalar-docs/#tag/leak-filter/GET/service/leak_filter_export_list/) lists your export jobs from the last 24 hours.
  </Step>
</Steps>

### A few things worth knowing

* `exact_match` defaults to `true`. Set it `false` to also pull country-code subsidiary domains (for example `acme.com.br` under `acme.com`).
* The `password` filter is case-**sensitive**; `username`, `server`, and `tags` are case-insensitive substring matches.
* Results paginate up to 1000 per page, and `page` × `page_size` can't exceed 50,000 — past that, narrow the filter or [export the results](#export-the-results).
