[旧版本,更新见72楼]Exa-Pool:一个优雅的exa搜索api号池,从此搜索api自由!

天哥在写bug 2025-12-09 16:02 1



闲来无事整了一个基于Cloudflare Workers的Exa API密钥号池,支持多密钥轮询、自动故障转移和可视化管理面板,从此实现exa自由 ^-^

基于cloudflare worker+D1数据库,全程无需服务器!谢谢cf大善人



功能特性



  • 密钥轮询 - Round-robin 策略自动分配请求到不同 API 密钥

  • 自动故障转移 - 密钥余额耗尽或失效时自动切换到下一个可用密钥

  • 智能重试 - 请求失败自动重试(最多 3 次)

  • 密钥状态管理 - 自动标记耗尽/失效密钥,支持批量验证

  • 访问控制 - 通过 Allowed Keys 控制谁可以使用代理服务

  • 可视化面板 - Web 管理界面,实时查看密钥状态和请求统计

  • 完整 API 兼容 - 兼容 Exa 官方 API


技术栈



  • Cloudflare Workers

  • Cloudflare D1 (SQLite)

  • Vanilla JavaScript (管理面板)


建议搭配食用 Exa搜索API白嫖60$额度


放个demo站出来,加了一些key,佬们随便刷 ^-^

与exa官方调用格式完全一样

https://exapool.chengtx.vip

调用apikey:linuxdo@chengtx

最新回复 (19)
  • 大帅哥 12-09 16:49
    1

    感谢大佬!

  • 天哥在写bug 楼主 12-09 16:57
    2

    放个demo站出来,加了一些key,佬们随便刷 ^-^

    https://exapool.chengtx.vip

    key:linuxdo@chengtx

  • Hiphop 突然 12-09 18:58
    3

    linuxdo@chengtx



    Invalid admin key

  • 天哥在写bug 楼主 12-09 19:33
    4

    是调用api的key了www,不是进后台的

  • creolophis 12-09 19:35
    5

    感谢大佬~

  • 光头不砍树 12-10 13:50
    6

    好用已star!大佬能不能把 research 的几个功能也实现了呢?

  • 天哥在写bug 楼主 12-10 15:03
    7

    好,下午晚点我看看文档给它加上,这几个功能平时我没怎么用

  • 光头不砍树 12-10 15:08
    8

    我已经在测了,待会给大佬提一个 pr

  • 光头不砍树 12-10 15:32
    9

    提了一个 pr,已经测过了,deep research 也可以反代了

  • 天哥在写bug 楼主 12-10 16:18
    10

    看到了,已经合并了,感谢!

  • GGBO 12-10 17:39
    11
    // ==UserScript==
    // @name EXA API 优惠码自动兑换器
    // @namespace http://tampermonkey.net/
    // @version 1.0
    // @description 自动尝试兑换 EXA API 的优惠码
    // @author You
    // @match https://dashboard.exa.ai/*
    // @grant GM_xmlhttpRequest
    // @grant GM_setValue
    // @grant GM_getValue
    // @grant GM_notification
    // ==/UserScript==

    (function () {
    'use strict';

    // =================== 配置区域 ===================
    const TEAM_ID = "YOUR_TEAM_ID_HERE"; // 请替换为你的 Team ID
    const COOKIE = "YOUR_COOKIE_HERE"; // 请替换为你的完整 Cookie

    const COUPON_PREFIX = "EXA";
    const COUPON_SUFFIX = "API";
    let START_NUMBER = 20;

    const MIN_DELAY = 1000; // 毫秒
    const MAX_DELAY = 5000;

    const MAX_ATTEMPTS = 0; // 0 表示无限循环
    // ================================================

    const BASE_URL = "https://dashboard.exa.ai/api/stripe/redeem-coupons";

    const HEADERS = {
    "accept": "application/json, text/plain, */*",
    "accept-language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
    "cache-control": "no-cache",
    "content-type": "application/json",
    "origin": "https://dashboard.exa.ai",
    "pragma": "no-cache",
    "referer": "https://dashboard.exa.ai/billing",
    "sec-ch-ua": '"Chromium";v="142", "Google Chrome";v="142", "Not_A Brand";v="99"',
    "sec-ch-ua-mobile": "?0",
    "sec-ch-ua-platform": '"macOS"',
    "sec-fetch-dest": "empty",
    "sec-fetch-mode": "cors",
    "sec-fetch-site": "same-origin",
    "user-agent": navigator.userAgent,
    "cookie": COOKIE
    };

    // 工具函数
    function getTimestamp() {
    return new Date().toLocaleString();
    }

    function randomDelay() {
    return Math.floor(Math.random() * (MAX_DELAY - MIN_DELAY + 1)) + MIN_DELAY;
    }

    function log(...args) {
    console.log(`[${getTimestamp()}]`, ...args);
    }

    function redeemCoupon(code) {
    return new Promise((resolve) => {
    GM_xmlhttpRequest({
    method: "POST",
    url: BASE_URL,
    headers: HEADERS,
    data: JSON.stringify({
    couponCode: code,
    description: "EXA API $50 Coupon",
    teamId: TEAM_ID
    }),
    onload: function (response) {
    try {
    const json = JSON.parse(response.responseText);
    resolve({ status: response.status, body: json });
    } catch (e) {
    resolve({ status: response.status, body: response.responseText });
    }
    },
    onerror: function (err) {
    resolve({ status: null, body: err });
    }
    });
    });
    }

    async function start() {
    if (TEAM_ID === "YOUR_TEAM_ID_HERE" || COOKIE === "YOUR_COOKIE_HERE") {
    alert("❌ 错误:请先填写你的 TEAM_ID 和 COOKIE!");
    return;
    }

    let currentNumber = GM_getValue("current_number", START_NUMBER);
    let attempt = GM_getValue("attempt", 0);
    let successCount = GM_getValue("success_count", 0);
    let failCount = GM_getValue("fail_count", 0);
    let successfulCodes = GM_getValue("successful_codes", []);

    log(`🎰 EXA 优惠码自动兑换脚本启动`);
    log(` Team ID: ${TEAM_ID.substring(0, 8)}...${TEAM_ID.slice(-4)}`);
    log(` 起始优惠码: ${COUPON_PREFIX}${currentNumber}${COUPON_SUFFIX}`);
    log(` 模式: 递增轮询 (+1)`);
    log(` 延时范围: ${MIN_DELAY / 1000}s - ${MAX_DELAY / 1000}s`);
    log(` 最大尝试次数: ${MAX_ATTEMPTS === 0 ? '无限' : MAX_ATTEMPTS}`);
    log("提示:按 F12 查看控制台日志,按 Ctrl+Shift+I 打开开发者工具");

    try {
    while (true) {
    attempt += 1;
    if (MAX_ATTEMPTS > 0 && attempt > MAX_ATTEMPTS) {
    log(`已达到最大尝试次数 (${MAX_ATTEMPTS}),退出。`);
    break;
    }

    const couponCode = `${COUPON_PREFIX}${currentNumber}${COUPON_SUFFIX}`;
    log(`第 ${attempt} 次尝试...`);
    log(` 🎫 优惠码: ${couponCode}`);

    const { status, body } = await redeemCoupon(couponCode);

    if (status === null) {
    log(`❌ 请求异常: ${body}`);
    failCount++;
    } else if (status === 200) {
    log(`✅ 成功! 响应:`, body);
    successCount++;
    successfulCodes.push(couponCode);
    GM_notification({
    title: "🎉 EXA 优惠码兑换成功",
    text: `兑换码: ${couponCode}`,
    timeout: 4000
    });
    } else if (status === 401 || status === 403) {
    log(`❌ 认证失败!请检查 Cookie 是否正确或已过期`);
    alert("认证失败,请检查 Cookie 或 Team ID!");
    break;
    } else {
    log(`❌ 失败 (状态码: ${status})`);
    log(`响应:`, body);
    failCount++;
    }

    currentNumber++;
    GM_setValue("current_number", currentNumber);
    GM_setValue("attempt", attempt);
    GM_setValue("success_count", successCount);
    GM_setValue("fail_count", failCount);
    GM_setValue("successful_codes", successfulCodes);

    const delay = randomDelay();
    log(`⏳ 等待 ${delay / 1000}s 后继续...`);
    await new Promise(r => setTimeout(r, delay));
    }
    } catch (e) {
    log("用户中断或发生错误:", e.message);
    }

    log(`📊 统计信息:`);
    log(` 总尝试次数: ${attempt}`);
    log(` 成功次数: ${successCount}`);
    log(` 失败次数: ${failCount}`);
    log(` 最后尝试的编号: ${currentNumber - 1}`);
    if (successfulCodes.length > 0) {
    log(`🎉 成功的优惠码:`);
    successfulCodes.forEach(code => log(` - ${code}`));
    }
    }

    // 在页面加载后运行
    window.addEventListener('load', () => {
    setTimeout(start, 2000); // 等待页面加载完成
    });

    })();



    还可以刷,就是不知道会不会清零。 注册了小号备用,^-^。 刷的先放着

  • torlee 12-10 17:50
    12

    cli的格式应该如何填写呢?原来的是这样



    {

    “args”: [

    “-y”,

    “exa-mcp-server”,

    “tools=get_code_context_exa,web_search_exa”

    ],

    “command”: “npx”,

    “env”: {

    “EXA_API_KEY”: “1118817e-dd36-45bd-9a2d-8b3afb62b2ca”

    }

    }


  • 藏于云海 12-10 18:03
    13

    还是没太搞懂这个exa的应该怎么玩,单纯搜索的话,似乎没必要刷那么多

  • 天哥在写bug 楼主 12-10 19:37
    14

    官方mcp应该不用key就可以用,有些佬是这么说的

    这个项目主要是放在自己开发的程序什么的来用,直接post接口拿搜索结果

  • 天哥在写bug 楼主 12-10 19:37
    15

    有agent模式,接的gork,联网搜索还是挺强的

  • 光头不砍树 12-17 13:00
    16

    修复了一个deep research的bug,佬有时间帮忙合一下

  • raco 12-17 13:01
    17


    跟一个 exa 搜索对话api的页面实现

  • 天哥在写bug 楼主 12-17 13:18
    18

    ok,我review下

  • 旅行的阿柒 12-24 16:42
    19

    大佬,能否支持一下 /context 的端点,我发现在 exa mcp中 get_code_context_exa 使用的是这个端点 /context

* 帖子来源Linux.do
返回