前置条件
- .NET 6.0+
- 一个 Firecrawl API 密钥 — 免费获取
配置
appsettings.json 中:
{
"Firecrawl": {
"ApiKey": "fc-YOUR-API-KEY",
"BaseUrl": "https://api.firecrawl.dev/v2"
}
}
export Firecrawl__ApiKey=fc-YOUR-API-KEY
创建服务
Services/FirecrawlService.cs:
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
public class FirecrawlService
{
private readonly HttpClient _http;
private readonly string _baseUrl;
public FirecrawlService(IConfiguration config)
{
_baseUrl = config["Firecrawl:BaseUrl"] ?? "https://api.firecrawl.dev/v2";
_http = new HttpClient();
_http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", config["Firecrawl:ApiKey"]);
}
public async Task<JsonDocument> SearchAsync(string query, int limit = 5)
{
var content = new StringContent(
JsonSerializer.Serialize(new { query, limit }),
Encoding.UTF8, "application/json");
var response = await _http.PostAsync($"{_baseUrl}/search", content);
response.EnsureSuccessStatusCode();
return JsonDocument.Parse(await response.Content.ReadAsStringAsync());
}
public async Task<JsonDocument> ScrapeAsync(string url)
{
var content = new StringContent(
JsonSerializer.Serialize(new { url }),
Encoding.UTF8, "application/json");
var response = await _http.PostAsync($"{_baseUrl}/scrape", content);
response.EnsureSuccessStatusCode();
return JsonDocument.Parse(await response.Content.ReadAsStringAsync());
}
public async Task<JsonDocument> InteractAsync(string url, string prompt, string? followUp = null)
{
// 1. 抓取以打开浏览器会话
var scrapeContent = new StringContent(
JsonSerializer.Serialize(new { url, formats = new[] { "markdown" } }),
Encoding.UTF8, "application/json");
var scrapeRes = await _http.PostAsync($"{_baseUrl}/scrape", scrapeContent);
scrapeRes.EnsureSuccessStatusCode();
var scrapeDoc = JsonDocument.Parse(await scrapeRes.Content.ReadAsStringAsync());
var scrapeId = scrapeDoc.RootElement
.GetProperty("data").GetProperty("metadata").GetProperty("scrapeId").GetString();
// 2. 发送第一个 prompt
var firstPrompt = new StringContent(
JsonSerializer.Serialize(new { prompt }),
Encoding.UTF8, "application/json");
await _http.PostAsync($"{_baseUrl}/scrape/{scrapeId}/interact", firstPrompt);
// 3. 发送后续 prompt
JsonDocument? result = null;
if (followUp != null)
{
var followUpContent = new StringContent(
JsonSerializer.Serialize(new { prompt = followUp }),
Encoding.UTF8, "application/json");
var followUpRes = await _http.PostAsync(
$"{_baseUrl}/scrape/{scrapeId}/interact", followUpContent);
followUpRes.EnsureSuccessStatusCode();
result = JsonDocument.Parse(await followUpRes.Content.ReadAsStringAsync());
}
// 4. 关闭会话
await _http.DeleteAsync($"{_baseUrl}/scrape/{scrapeId}/interact");
return result ?? scrapeDoc;
}
}
注册并使用
Program.cs 中:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<FirecrawlService>();
var app = builder.Build();
app.MapPost("/api/search", async (FirecrawlService firecrawl, SearchRequest req) =>
{
var result = await firecrawl.SearchAsync(req.Query, req.Limit);
return Results.Ok(result.RootElement);
});
app.MapPost("/api/scrape", async (FirecrawlService firecrawl, ScrapeRequest req) =>
{
var result = await firecrawl.ScrapeAsync(req.Url);
return Results.Ok(result.RootElement);
});
app.MapPost("/api/interact", async (FirecrawlService firecrawl, InteractRequest req) =>
{
var result = await firecrawl.InteractAsync(req.Url, req.Prompt, req.FollowUp);
return Results.Ok(result.RootElement);
});
app.Run();
record SearchRequest(string Query, int Limit = 5);
record ScrapeRequest(string Url);
record InteractRequest(string Url, string Prompt, string? FollowUp = null);
运行
dotnet run
试一试
# 进行网页搜索
curl -X POST http://localhost:5000/api/search \
-H "Content-Type: application/json" \
-d '{"query": "firecrawl web scraping"}'
# 抓取页面
curl -X POST http://localhost:5000/api/scrape \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}'
# 与页面交互
curl -X POST http://localhost:5000/api/interact \
-H "Content-Type: application/json" \
-d '{"url": "https://www.amazon.com", "prompt": "Search for iPhone 16 Pro Max", "followUp": "Click on the first result and tell me the price"}'
下一步
搜索文档
进行网页搜索并获取完整页面内容
抓取文档
所有抓取选项,包括 formats、actions 和代理
交互文档
点击、填写表单并提取动态内容
API 参考
完整的 REST API 文档

