مفتاح CaptchaAI API لا مكان له داخل الكود. مكانه الصحيح متغيّر بيئة واحد اسمه CAPTCHAAI_API_KEY يُقرأ وقت التشغيل، فيصل إليه السكربت بينما يبقى المستودع خالياً منه. سطر واحد مثل os.environ["CAPTCHAAI_API_KEY"] يجعل المفتاح يعيش في بيئة التشغيل وحدها، ويترك الكود قابلاً للمشاركة دون أن يحمل معه بيانات اعتمادك.
الدليل التالي يتتبّع المفتاح في مساره الفعلي داخل أي فريق: جهاز المطوّر، ثم الخادم أو الحاوية، ثم خط CI/CD الذي يشغّل السكربت دون تدخل بشري. في كل محطة طريقة واحدة نظيفة لتمرير المفتاح، وخطأ واحد يتكرر في مراجعات الكود.
من أين يتسرّب مفتاح الـ API عملياً
قبل الخطوات، هذه النقاط التي يخرج منها المفتاح دون أن ينتبه أحد:
- تاريخ المستودع — حذف السطر لاحقاً لا يحذف المفتاح من الـ commits السابقة.
- السجلات — أي
printأوconsole.logللطلب كاملاً ينقل المفتاح إلى أدوات تجميع السجلات. - طبقات صور Docker — المفتاح المكتوب أثناء البناء يسافر مع الصورة إلى كل من يسحبها.
- المشاركة اليدوية — رسالة بريد أو محادثة فريق تعني نسخة دائمة خارج سيطرتك.
مثال قريب من الواقع: فريق في القاهرة يبني لوحة لمتابعة أسعار المنافسين في متاجر الخليج، ويستعين بمطوّر مستقل لأسبوعين قبل موسم التخفيضات. المفتاح مكتوب في scraper.py، والمستودع يُشارك مع المطوّر المستقل ثم مع فريق التصميم، وبعد شهر لا يعرف أحد كم نسخة من المفتاح تعيش خارج الفريق. متغير البيئة يحسم المسألة: الكود يُشارَك، والمفتاح لا.
الخطوة الأولى: ملف .env على جهاز التطوير
خطوتان وترتيبهما مهم، لأن الملف الذي دخل التتبّع مرة واحدة يبقى في تاريخ المستودع:
- ملف
.envفي جذر المشروع يحمل المفتاح كما هو من لوحة التحكم. - سطر
.envداخل.gitignoreقبل أيgit add.
CAPTCHAAI_API_KEY=your_actual_api_key_here
# .gitignore
.env
.env.local
.env.production
Python: قراءة المفتاح عبر python-dotenv
ثبّت المكتبة أولاً:
pip install python-dotenv
ثم حمّل الملف واقرأ المفتاح باسمه. استخدام os.environ["..."] بالأقواس المربعة مقصود: إن كان المتغير غائباً يتوقف السكربت فوراً بدل أن يرسل طلباً بمفتاح فارغ ويعود برمز خطأ غامض.
import os
from dotenv import load_dotenv
load_dotenv()
API_KEY = os.environ["CAPTCHAAI_API_KEY"]
# Use in API calls
import requests
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": "6Le-SITEKEY",
"pageurl": "https://example.com",
"json": "1",
})
print(resp.json())
JavaScript: النمط نفسه مع dotenv
npm install dotenv
في Node.js يفيد التحقق الصريح من وجود المتغير قبل أول طلب، لأن undefined يُرسَل بصمت داخل الـ query string ويعود بخطأ صلاحية بدل خطأ إعداد:
require('dotenv').config();
const API_KEY = process.env.CAPTCHAAI_API_KEY;
if (!API_KEY) {
console.error('CAPTCHAAI_API_KEY not set');
process.exit(1);
}
// Use in API calls
const axios = require('axios');
const resp = await axios.post('https://ocr.captchaai.com/in.php', null, {
params: {
key: API_KEY,
method: 'userrecaptcha',
googlekey: '6Le-SITEKEY',
pageurl: 'https://example.com',
json: 1,
},
});
console.log(resp.data);
متغيرات النظام حين لا يوجد ملف .env
- خادم دائم — الخدمة تعمل تحت systemd أو من
crontab، ولا جذر مشروع يحمل ملف.env؛ المفتاح يُضبط على مستوى نظام التشغيل. - جلسة مؤقتة — اتصال SSH لتشغيل السكربت يدوياً، والمتغير فيه يعيش إلى أن تُغلق الجلسة.
Linux و macOS
export CAPTCHAAI_API_KEY="your_actual_api_key_here"
# Persist across sessions — add to ~/.bashrc or ~/.zshrc
echo 'export CAPTCHAAI_API_KEY="your_actual_api_key_here"' >> ~/.bashrc
Windows عبر PowerShell
$env:CAPTCHAAI_API_KEY = "your_actual_api_key_here"
# Persist permanently
[System.Environment]::SetEnvironmentVariable("CAPTCHAAI_API_KEY", "your_actual_api_key_here", "User")
انتبه إلى نقطة تربك كثيرين: export في جلسة واحدة لا يراه cron ولا systemd — هذه البيئات تبدأ بمتغيرات شبه فارغة، فاضبط المفتاح في ملف الخدمة أو في crontab نفسه.
Docker: المفتاح يدخل الحاوية ولا يُخزَّن فيها
أبسط صيغة تمرّر المتغير عند التشغيل فقط:
docker run -e CAPTCHAAI_API_KEY="your_key" my-scraper
Docker Compose
# docker-compose.yml
services:
scraper:
image: my-scraper
environment:
- CAPTCHAAI_API_KEY=${CAPTCHAAI_API_KEY}
${CAPTCHAAI_API_KEY}يقرأ القيمة من بيئة المضيف لحظة التشغيل.- ملف الإنشاء نفسه يبقى خالياً من المفتاح، فيُرفع مع المشروع دون قلق.
Docker Secrets في وضع Swarm
للبيئات الإنتاجية الأكبر، أسرار Docker أنظف من متغيرات البيئة لأن السر يُحمَّل كملف داخل الحاوية ولا يظهر في docker inspect:
echo "your_actual_api_key_here" | docker secret create captchaai_key -
# docker-compose.yml (Swarm mode)
services:
scraper:
image: my-scraper
secrets:
- captchaai_key
secrets:
captchaai_key:
external: true
ثم يُقرأ الملف من الكود مباشرة:
with open("/run/secrets/captchaai_key") as f:
API_KEY = f.read().strip()
خطوط CI/CD: خزنة أسرار بدل ملفات
GitHub Actions
# .github/workflows/scrape.yml
jobs:
scrape:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: python scraper.py
env:
CAPTCHAAI_API_KEY: ${{ secrets.CAPTCHAAI_API_KEY }}
- موضع الإضافة: Settings ← Secrets and variables ← Actions ← New repository secret.
- بعد الحفظ لا يمكن عرض القيمة مرة أخرى، وأي محاولة لطباعتها في السجل تظهر مموّهة تلقائياً.
GitLab CI
# .gitlab-ci.yml
scrape:
script:
- python scraper.py
variables:
CAPTCHAAI_API_KEY: $CAPTCHAAI_API_KEY
- موضع الإضافة: Settings ← CI/CD ← Variables.
- فعّل Masked حتى لا تظهر القيمة في سجل التنفيذ، وProtected إن كان المفتاح مخصصاً للفرع الإنتاجي وحده.
تحقّق من المفتاح قبل أول طلب حلّ
الفشل المتأخر مكلف: سكربت يعمل عشر دقائق ثم يتوقف لأن المتغير غير مضبوط في الخادم. افحص المفتاح والرصيد في أول سطر من التشغيل عبر res.php مع action=getbalance:
import os
import sys
import requests
API_KEY = os.environ.get("CAPTCHAAI_API_KEY")
if not API_KEY:
print("ERROR: CAPTCHAAI_API_KEY environment variable not set")
sys.exit(1)
# Verify key works
resp = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "getbalance", "json": "1"
}).json()
if resp["status"] != 1:
print(f"ERROR: Invalid API key — {resp['request']}")
sys.exit(1)
print(f"API key valid — balance: ${float(resp['request']):.2f}")
نتيجة الفحص تفصل بين حالتين تُخلَطان في تذاكر الدعم: مفتاح خاطئ أو غير مفعّل، مقابل خطة لا تتسع للتزامن المطلوب. خطط CaptchaAI مبنية على عدد الـ threads المتزامنة مع حلول غير محدودة داخل كل thread — BASIC بـ 15 دولاراً شهرياً مع 5 threads، وADVANCE بـ 90 دولاراً مع 50 thread — فبطء الخط عند الذروة مسألة تزامن، ورفض المفتاح مسألة إعداد.
إدارة أكثر من مفتاح: تطوير وإنتاج في مشروع واحد
الفصل بين مفتاح التطوير ومفتاح الإنتاج يمنع اختبارات reCAPTCHA v2 المحلية من استهلاك تزامن الخط الإنتاجي، ويجعل سحب أي مفتاح إجراءً محدود الأثر. يمكن تمرير أكثر من مفتاح عبر قيمة واحدة مفصولة بفواصل:
CAPTCHAAI_KEYS=key1,key2,key3
keys = os.environ["CAPTCHAAI_KEYS"].split(",")
النمط نفسه يفيد عند الانتقال التدريجي من مفتاح قديم إلى جديد. للتفاصيل راجع إدارة المفاتيح المتعددة وتدويرها.
أخطاء تتكرر في مراجعات الكود
| الخطأ | ما الذي يحدث | الإصلاح |
|---|---|---|
رفع .env إلى Git |
المفتاح يبقى في تاريخ المستودع حتى بعد حذف الملف | أضف .env إلى .gitignore قبل أول commit |
| طباعة الطلب كاملاً في السجلات | المفتاح يظهر لكل من يملك صلاحية قراءة السجلات | اطبع آخر 4 خانات فقط، أو احذف السطر بعد التصحيح |
| كتابة المفتاح داخل Dockerfile | المفتاح يُخبز في طبقات الصورة ويسافر معها | مرّر ENV وقت التشغيل لا أثناء البناء |
| إرسال المفتاح عبر بريد أو محادثة | نسخة دائمة خارج سيطرة الفريق | استخدم خزنة أسرار، ثم دوّر المفتاح بعد انتهاء المهمة |
| مفتاح واحد لكل البيئات | تعطّل الاختبارات يوقف الإنتاج معها | مفتاح لكل بيئة، وصلاحيات منفصلة |
قائمة تحقق قبل أول نشر
.envمُدرَج في.gitignoreولم يدخل التتبّع في أي commit سابق.- لا يوجد مفتاح مكتوب حرفياً في أي ملف مصدري أو ملف إعداد.
- أسرار CI/CD مضبوطة ومفعّل عليها التمويه في السجلات.
- فحص
getbalanceيعمل عند بدء التشغيل ويوقف السكربت عند الفشل. - عناوين IP الخاصة بخوادمك مضبوطة عبر القائمة البيضاء لعناوين IP وأمان المفتاح.
أسئلة شائعة
لماذا يشتكي السكربت من غياب المتغير رغم أنني ضبطته؟
في الغالب لأن الجلسة التي ضُبط فيها المتغير ليست الجلسة التي تشغّل السكربت. الأمر export يعيش داخل الطرفية الحالية فقط، ولا ينتقل إلى cron ولا إلى خدمة systemd ولا إلى حاوية Docker. اضبط المتغير في ملف الخدمة، أو مرّره صراحة بـ -e عند تشغيل الحاوية.
كيف أمنع ظهور المفتاح في السجلات أثناء تتبّع الأخطاء؟
لا تطبع كائن الطلب كاملاً؛ اطبع الحقول التي تحتاجها فقط. وإن أردت تأكيد أن المفتاح المحمَّل صحيح فاعرض آخر أربع خانات منه، وفعّل التمويه على المتغير في CI.
متى أنتقل من ملف .env إلى مدير أسرار سحابي؟
ملف .env مع .gitignore كافٍ لجهاز مطوّر واحد. مع أول خادم إنتاجي مشترك أو فريق يتغيّر أعضاؤه، انتقل إلى AWS Secrets Manager أو Google Secret Manager أو Azure Key Vault. الفارق ليس التشفير بل التدقيق: من قرأ السر ومتى.
هل أحتاج إلى تدوير المفتاح عند مغادرة أحد أعضاء الفريق؟
نعم، والعملية تستغرق دقائق. أي شخص عمل على المستودع أو الخادم يُفترض أنه رأى المفتاح. أنشئ مفتاحاً جديداً من لوحة التحكم، حدّث المتغير في البيئات والخزائن، ثم أوقف القديم.
ماذا أفعل فوراً إذا ظهر المفتاح في مستودع عام أو لقطة شاشة؟
ابدأ بالتدوير لا بالحذف. إنشاء مفتاح بديل وتعطيل القديم هو ما يوقف الاستخدام غير المصرّح به، أما حذف الملف فلا يغيّر شيئاً لأن النسخ المؤرشفة تبقى متاحة. ثم أضف تقييد عناوين IP كطبقة ثانية.
احصل على مفتاحك واربطه بمتغير بيئة من أول يوم
أنشئ حسابك على captchaai.com، ثم انسخ المفتاح مباشرة إلى .env أو إلى خزنة أسرار مشروعك.