/**
* Firecrawl API Client
* Handles all communication with the Firecrawl API
*/
import {
FirecrawlConfig,
FirecrawlAgentRequest,
FirecrawlAgentResponse,
FirecrawlAgentJob,
FirecrawlScrapeRequest,
FirecrawlScrapeResponse,
FirecrawlSearchRequest,
FirecrawlSearchResponse,
} from '../types/firecrawl.js';
export class FirecrawlClient {
private apiKey: string;
private apiBase: string;
constructor(config: FirecrawlConfig) {
this.apiKey = config.apiKey;
this.apiBase = config.apiBase || 'https://api.firecrawl.dev';
}
/**
* Execute agent request synchronously (waits for completion)
*/
async executeAgent(request: FirecrawlAgentRequest): Promise<FirecrawlAgentResponse> {
try {
const response = await fetch(`${this.apiBase}/v1/agent`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.apiKey}`,
},
body: JSON.stringify(request),
});
const data = await response.json() as any;
if (!response.ok) {
return {
success: false,
error: data.error || `HTTP ${response.status}: ${response.statusText}`,
};
}
return {
success: true,
data: data.data,
creditsUsed: data.creditsUsed,
};
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error',
};
}
}
/**
* Start agent job asynchronously (returns job ID immediately)
*/
async startAgent(request: FirecrawlAgentRequest): Promise<FirecrawlAgentResponse> {
try {
const response = await fetch(`${this.apiBase}/v1/agent/start`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.apiKey}`,
},
body: JSON.stringify(request),
});
const data = await response.json() as any;
if (!response.ok) {
return {
success: false,
error: data.error || `HTTP ${response.status}: ${response.statusText}`,
};
}
return {
success: true,
id: data.id,
};
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error',
};
}
}
/**
* Get agent job status
*/
async getAgentStatus(jobId: string): Promise<FirecrawlAgentJob> {
try {
const response = await fetch(`${this.apiBase}/v1/agent/${jobId}`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${this.apiKey}`,
},
});
const data = await response.json() as any;
if (!response.ok) {
return {
id: jobId,
status: 'failed',
error: data.error || `HTTP ${response.status}: ${response.statusText}`,
};
}
return {
id: jobId,
status: data.status,
data: data.data,
error: data.error,
creditsUsed: data.creditsUsed,
progress: data.progress,
};
} catch (error) {
return {
id: jobId,
status: 'failed',
error: error instanceof Error ? error.message : 'Unknown error',
};
}
}
/**
* Scrape a single URL
*/
async scrape(request: FirecrawlScrapeRequest): Promise<FirecrawlScrapeResponse> {
try {
const response = await fetch(`${this.apiBase}/v1/scrape`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.apiKey}`,
},
body: JSON.stringify(request),
});
const data = await response.json() as any;
if (!response.ok) {
return {
success: false,
error: data.error || `HTTP ${response.status}: ${response.statusText}`,
};
}
return {
success: true,
data: data.data,
};
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error',
};
}
}
/**
* Search the web and scrape results
*/
async search(request: FirecrawlSearchRequest): Promise<FirecrawlSearchResponse> {
try {
const response = await fetch(`${this.apiBase}/v1/search`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.apiKey}`,
},
body: JSON.stringify(request),
});
const data = await response.json() as any;
if (!response.ok) {
return {
success: false,
error: data.error || `HTTP ${response.status}: ${response.statusText}`,
};
}
return {
success: true,
data: data.data,
};
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error',
};
}
}
}