Free AI Models Comparison: OpenRouter vs Together vs Groq
A practical guide to choosing the best free AI API for your project in 2024.
Introduction
With dozens of free AI models available via unified APIs, choosing the right provider saves time and money. This guide compares the three major free-tier providers: OpenRouter, Together.ai, and Groq.
Quick Comparison
| Feature | OpenRouter | Together.ai | Groq |
|---|---|---|---|
| Free Models | 50+ | 20+ | 10+ |
| Rate Limit | 20 req/min | 60 req/min | 30 req/min |
| Speed | Medium | Medium | Fastest |
| Model Variety | Best | Good | Limited |
| API Format | OpenAI-compatible | OpenAI-compatible | OpenAI-compatible |
OpenRouter: Maximum Variety
import requests
import os
def openrouter(model: str = "google/gemini-2.0-flash-exp:free"):
return {
"url": "https://openrouter.ai/api/v1/chat/completions",
"headers": {
"Authorization": f"Bearer {os.getenv('OPENROUTER_API_KEY')}",
"Content-Type": "application/json"
},
"models": {
"code": "google/gemini-2.0-flash-exp:free",
"chat": "meta-llama/llama-3.1-8b-instruct:free",
"fast": "mistralai/mistral-7b-instruct:free",
"reasoning": "deepseek/deepseek-r1:free"
}
}
Best for: Projects needing model variety, easy model switching
Together.ai: Balanced Performance
import requests
import os
def together(model: str = "meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo"):
return {
"url": "https://api.together.xyz/v1/chat/completions",
"headers": {
"Authorization": f"Bearer {os.getenv('TOGETHER_API_KEY')}",
"Content-Type": "application/json"
},
"models": {
"general": "meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo",
"code": "codellama/CodeLlama-7b-Instruct-hf",
"chat": "mistralai/Mistral-7B-Instruct-v0.3"
}
}
Best for: Consistent performance, good open-source model selection
Groq: Maximum Speed
import requests
import os
def groq(model: str = "llama-3.1-8b-instant"):
return {
"url": "https://api.groq.com/openai/v1/chat/completions",
"headers": {
"Authorization": f"Bearer {os.getenv('GROQ_API_KEY')}",
"Content-Type": "application/json"
},
"models": {
"fast": "llama-3.1-8b-instant",
"large": "llama-3.1-70b-versatile",
"mixtral": "mixtral-8x7b-32768"
}
}
Best for: Low-latency applications, real-time chat
Unified Client Pattern
import requests
import os
from typing import Optional
class FreeAIClient:
def __init__(self):
self.providers = {
"openrouter": {
"url": "https://openrouter.ai/api/v1/chat/completions",
"key": os.getenv("OPENROUTER_API_KEY"),
"default_model": "google/gemini-2.0-flash-exp:free"
},
"together": {
"url": "https://api.together.xyz/v1/chat/completions",
"key": os.getenv("TOGETHER_API_KEY"),
"default_model": "meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo"
},
"groq": {
"url": "https://api.groq.com/openai/v1/chat/completions",
"key": os.getenv("GROQ_API_KEY"),
"default_model": "llama-3.1-8b-instant"
}
}
def chat(self, prompt: str, provider: str = "openrouter",
model: Optional[str] = None, **kwargs) -> str:
p = self.providers[provider]
if not p["key"]:
raise ValueError(f"No API key for {provider}")
response = requests.post(
p["url"],
headers={
"Authorization": f"Bearer {p['key']}",
"Content-Type": "application/json"
},
json={
"model": model or p["default_model"],
"messages": [{"role": "user", "content": prompt}],
"temperature": 0.7,
"max_tokens": 500,
**kwargs
},
timeout=30
)
response.raise_for_status()
return response.json()["choices"][0]["message"]["content"]
def with_fallback(self, prompt: str, providers: list = None) -> str:
"""Try providers in order until one succeeds."""
providers = providers or ["groq", "together", "openrouter"]
for provider in providers:
try:
return self.chat(prompt, provider)
except Exception as e:
print(f"{provider} failed: {e}")
raise Exception("All providers failed")
# Usage
client = FreeAIClient()
print(client.chat("Hello!", "openrouter"))
print(client.with_fallback("Hello!"))
Rate Limit Handling
import time
import requests
from functools import wraps
def rate_limited(max_per_minute: int):
min_interval = 60.0 / max_per_minute
last_call = [0.0]
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
elapsed = time.time() - last_call[0]
if elapsed < min_interval:
time.sleep(min_interval - elapsed)
last_call[0] = time.time()
return func(*args, **kwargs)
return wrapper
return decorator
@rate_limited(20) # OpenRouter limit
def openrouter_call(prompt: str) -> str:
# ... implementation
pass
Recommendation by Use Case
| Use Case | Recommended Provider | Model |
|---|---|---|
| Code generation | OpenRouter | google/gemini-2.0-flash-exp:free |
| Chat bot | Groq | llama-3.1-8b-instant |
| Creative writing | Together.ai | mistralai/Mistral-7B-Instruct-v0.3 |
| Reasoning tasks | OpenRouter | deepseek/deepseek-r1:free |
| High volume | Together.ai | meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo |
| Low latency | Groq | llama-3.1-8b-instant |
| Model experimentation | OpenRouter | Any |
Getting Started Checklist
- [ ] Get free API keys from all three providers
- [ ] Store in
.envfile (never commit!) - [ ] Test each with a simple prompt
- [ ] Implement fallback logic
- [ ] Add rate limiting
- [ ] Monitor usage in provider dashboards
Conclusion
Start with OpenRouter for maximum flexibility — one key gives access to 50+ models. Add Groq for speed-critical paths and Together.ai for volume. The unified client pattern above makes switching trivial.
All three offer generous free tiers sufficient for development and small production workloads.
Part of the Free AI APIs series on Dev.to
Top comments (0)