English | 中文 | हिंदी | Español | Français | العربية | বাংলা | Русский | Português | Bahasa Indonesia
Python module that provides access to free AI keys from the
alistaitsacle/free-llm-api-keys
repository in OpenAI format. It downloads, parses, and caches the source README.md,
then exposes ready-to-use clients by model type
(Text, Image, TTS, Embeddings) that automatically rotate
through available keys.
⚠️ Public and shared keys: they can be exhausted (budget) or expired (24–48 h). That is why the client tries all the keys for a model one after the other until it finds one that works.
- 🔄 Auto-update: on every launch, refreshes the list from GitHub if the cache is stale (1 h TTL), otherwise uses the cache.
- 💾 Local cache + offline mode: automatic fallback to the cache (even if stale) if the network is unavailable.
- 🔁 Key auto-rotation: switches to the next key when a key is rejected (budget / expired / rate-limit), with retries on transient network errors.
- 🧩 4 model types:
chat,generate_image,tts,embeddings.
This package is not yet published on PyPI. You can install it directly from GitHub.
uv add "git+https://github.com/laurentvv/free-llm-api-keys-python.git"pip install "git+https://github.com/laurentvv/free-llm-api-keys-python.git"git clone https://github.com/laurentvv/free-llm-api-keys-python.git
cd free-llm-api-keys-python
uv sync
uv run pytestfrom free_llm_api_keys import FreeLLMClient
# Upon instantiation, the catalog updates from GitHub if needed
# (otherwise it uses the local cache).
client = FreeLLMClient(type="texte")
response = client.chat([{"role": "user", "content": "Hello!"}])
print(response)from free_llm_api_keys import FreeLLMClient
client = FreeLLMClient(type="texte")
text = client.chat(
[{"role": "user", "content": "Explain photosynthesis in 2 sentences."}],
temperature=0.7,
)
print(text)client = FreeLLMClient(type="image")
urls = client.generate_image("A cyberpunk fox in a neon forest", n=1, size="1024x1024")
print(urls[0]) # Generated image URLclient = FreeLLMClient(type="tts")
audio: bytes = client.tts("Hello, this is a test.", voice="alloy")
Path("output.mp3").write_bytes(audio)client = FreeLLMClient(type="embeddings")
vectors = client.embeddings(["text one", "text two"])
print(len(vectors), len(vectors[0])) # 2 vectors of dimension Nfrom free_llm_api_keys import Catalog, ModelCategory
catalog = Catalog.load()
print(catalog.list_models()) # all
print(catalog.list_models(ModelCategory.IMAGE)) # images only
print(len(catalog), "total keys")| Variable / parameter | Default | Role |
|---|---|---|
FREE_LLM_CACHE_DIR (env) |
~/.cache/free-llm-api-keys |
Cache directory |
| Cache TTL | 3600 s (1 h) |
Catalog.load(ttl_seconds=...) |
| Base URL | https://aiapiv2.pekpik.com/v1 |
FreeLLMClient(base_url=...) |
Force an update from GitHub:
catalog = Catalog.load(force_refresh=True)- 1st launch: downloads the
README.mdfrom GitHub, parses it, and writes the local cache. - Subsequent launches (< 1 h): uses the cache, no network requests.
- Stale cache (> 1 h): re-downloads and updates the cache.
- Network unavailable: uses the existing cache (even if stale);
raises
FetchErroronly if no cache exists.
| Exception | When? |
|---|---|
NoKeysAvailableError |
The requested model does not exist in the catalog. |
AllKeysExhaustedError |
All keys for the model have failed. |
FetchError |
Impossible to download the README and no cache available. |
ParseError |
The structure of the README has changed and is no longer parsable. |
src/free_llm_api_keys/
├── __init__.py # Public API
├── fetcher.py # README download (httpx + ETag)
├── parser.py # markdown parsing -> KeyEntry
├── classifier.py # model type (text/image/tts/embeddings)
├── cache.py # local JSON cache + TTL + offline fallback
├── catalog.py # fetch + parse + cache orchestration
├── client.py # FreeLLMClient : OpenAI + auto-rotation + retry
└── exceptions.py
See the source repository for the status of the keys. This module is an unofficial client around these public keys.
