---
name: browser_profile_list
kind: function
lang: py
domain: browser
version: "1.0.0"
purity: impure
signature: "def browser_profile_list(status: str | None = None, base_url: str = 'http://127.0.0.1:8771') -> dict"
description: "Lista los perfiles de Chromium del catalogo del service osint_db con su numero de cuentas. Hace POST /api/query (read-only) con un SELECT que une browser_profiles LEFT JOIN un agregado COUNT de browser_profile_accounts por profile_dir, y mapea columns->rows a una lista de dicts con claves profile_dir, label, persona, purpose, status, note_path, n_accounts. Filtra por status si se pasa. El service responde SIEMPRE HTTP 200 con body {status:ok|error}. Impura (red). No lanza: devuelve dict de estado."
tags: [browser-profiles, osint, chromium, profile, multicuenta]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_py_core"
imports: []
tested: true
tests: ["test_golden_lista_perfiles_mapea_columns_a_dicts", "test_edge_filtro_status_agrega_where_y_param", "test_error_query_falla_devuelve_status_error"]
test_file_path: "python/functions/browser/browser_profile_list_test.py"
file_path: "python/functions/browser/browser_profile_list.py"
params:
  - name: status
    desc: "Si no es None, filtra por estado del perfil (ej. 'active', 'archived', 'burned'). None -> devuelve todos los perfiles."
  - name: base_url
    desc: "Base del service osint_db. Default http://127.0.0.1:8771."
output: "dict de estado. Caso ok: {status:'ok', profiles: list de dicts con claves profile_dir, label, persona, purpose, status, note_path, n_accounts (int: cuentas asociadas al perfil)}. Caso error (service caido o query rechazada): {status:'error', error: str}."
---

## Ejemplo

```python
import sys, os
sys.path.insert(0, os.path.join("python", "functions"))
from browser.browser_profile_list import browser_profile_list

res = browser_profile_list()             # todos los perfiles
for p in res["profiles"]:
    print(p["profile_dir"], p["persona"], p["n_accounts"])

activos = browser_profile_list(status="active")  # solo perfiles activos
print(len(activos["profiles"]))
```

## Cuando usarla

Cuando necesites un inventario rapido de los perfiles Chromium catalogados para OSINT:
ver que personas existen, su proposito y cuantas cuentas tiene cada uno, antes de
abrir uno con `browser_profile_open` o inspeccionarlo a fondo con `browser_profile_show`.
Usa `status="active"` para filtrar los perfiles vivos y descartar los archivados/quemados.

## Gotchas

- **Impura**: hace red (HTTP POST /api/query al service). El service `osint_db` debe estar
  vivo en `http://127.0.0.1:8771`. Si esta caido, devuelve `{status:'error', error:'... inaccesible'}`
  sin lanzar.
- **El codigo HTTP NO indica exito**: el service responde SIEMPRE HTTP 200 con body
  `{status:ok|error}`; se parsea el body.
- **Read-only**: usa `/api/query` con un SELECT; no muta nada en el catalogo.
- **n_accounts viene de un LEFT JOIN agregado**: los perfiles sin cuentas aparecen con
  `n_accounts=0` (COALESCE), no se omiten.
- **No expone secretos**: este listado NO trae los `secret_ref` de las cuentas (solo el
  conteo). Para ver cuentas y sus referencias usa `browser_profile_show`.

## Notas

Usa el helper compartido `python/functions/browser/_osint_db_client.py` (modulo privado
no indexado) para el POST sobre `urllib.request` de stdlib (sin `requests`). El SELECT
ordena por `profile_dir`. Timeout HTTP de 10s.
