Your current /api/scrape endpoint is synchronous—the client waits for the entire scraping to complete:
POST /api/scrape
// Client waits... (5-30 seconds)
// Returns: { success: true, data: {...} }Problems with this approach:
- ⏰ Timeout issues: Long-running scrapes (30+ seconds) cause HTTP timeouts
- 🔒 Resource blocking: Client connection stays open, wasting server resources
- 📱 Poor UX: User sees "loading..." for 30+ seconds
- 🚫 Browser pool exhaustion: Limited concurrent requests due to connection limits
Step 1: Submit job
POST /api/scrape-async
Response: { "success": true, "jobId": "abc123", "status": "queued" }Step 2: Check status
GET /api/jobs/abc123
Response: { "jobId": "abc123", "status": "processing", "progress": "40%" }Step 3: Get results
GET /api/jobs/abc123
Response: { "jobId": "abc123", "status": "completed", "data": {...} }Scrape 100 product pages—would take 30+ minutes synchronously.
POST /api/scrape-batch
{
"urls": ["url1", "url2", ...], // 100 URLs
"selectors": {...}
}
Response: { "batchId": "batch456", "estimatedTime": "25 minutes" }Login → Navigate → Search → Paginate → Extract
POST /api/scrape-flow
{
"steps": [
{ "action": "login", "credentials": {...} },
{ "action": "search", "query": "laptops" },
{ "action": "paginate", "pages": 10 },
{ "action": "extract", "selectors": {...} }
]
}POST /api/scrape-schedule
{
"url": "https://prices.com/product/123",
"schedule": "daily",
"selectors": { "price": ".price" }
}| Use Case | Recommended | Why |
|---|---|---|
| Single page, simple selectors | Sync | Fast (<10s), immediate results needed |
| Price monitoring dashboard | Sync | Real-time data for user interaction |
| Bulk product catalog | Async | Long-running (minutes/hours) |
| Scheduled monitoring | Async | Background processing |
| User-initiated reports | Async | Better UX with progress updates |
| API integrations | Both | Sync for real-time, async for batch |
POST /api/scrape?async=true // Optional async flag
POST /api/scrape // Default sync behaviorPOST /api/scrape // Sync (current)
POST /api/scrape-async // Async with job queue
GET /api/jobs/:jobId // Job status/resultsPOST /api/scrape-async
// WebSocket: { jobId: "abc", status: "processing", progress: 60% }
// WebSocket: { jobId: "abc", status: "completed", data: {...} }Start with sync (what you have), add async later when you need:
- Keep sync for now—works great for single-page scraping
- Add async when you encounter:
- Scraping taking >30 seconds consistently
- Users requesting batch processing
- Timeout errors becoming frequent
- Need for scheduling/automation
Simple async implementation:
- Use Redis/database for job queue
- Background worker processes jobs
- REST endpoints for job status/results
Bottom line:
Async endpoints become important when scraping duration exceeds user patience (~10-15 seconds) or when you need batch/scheduled processing. For your current single-page use case, sync is perfectly fine.