Skip to content

Login scraping

Use /interact when the target content sits behind a login, cookie wall, or multi-step browser journey.

First pass: create the session

Log in and extract

```bash curl https://api.faircompany.ai/v1/crawl/interact \ -X POST \ -H "Authorization: Bearer fc_live_xxx" \ -H "Content-Type: application/json" \ -d '{ "url": "https://example.com/login", "actions": [ { "type": "fill", "selector": "#email", "value": "user@example.com" }, { "type": "fill", "selector": "#password", "value": "super-secret" }, { "type": "click", "selector": "button[type=\"submit\"]" }, { "type": "wait_for_selector", "selector": ".dashboard", "timeout_ms": 10000 }, { "type": "extract", "format": "markdown" } ] }' ```

Reuse the same profile

const login = await fc.interact({
url: "https://example.com/login",
actions: [
{ type: "fill", selector: "#email", value: process.env.LOGIN_EMAIL! },
{ type: "fill", selector: "#password", value: process.env.LOGIN_PASSWORD! },
{ type: "click", selector: 'button[type="submit"]' },
{ type: "wait_for_selector", selector: ".dashboard", timeout_ms: 10000 },
],
});
const billing = await fc.interact({
url: "https://example.com/settings/billing",
profile_id: login.profile_id,
actions: [{ type: "extract", format: "markdown" }],
});

Practical rules

  • persist the returned profile_id with the customer workflow that owns the session
  • break long journeys into multiple /interact calls instead of a single oversized action list
  • use wait_for_selector instead of arbitrary sleeps when you know the UI signal you need
  • prefer /scrape for public follow-up pages and reserve /interact for the truly stateful part of the job