Documentation Index
Fetch the complete documentation index at: https://docs.geekflare.com/llms.txt
Use this file to discover all available pages before exploring further.
This guide uses the official geekflare-api Python SDK inside a Django project. We’ll create a reusable service class, wire it into Django views, and keep secrets out of source control with python-decouple.
Prerequisites
Installation
pip install geekflare-api python-decouple
Or with uv:
uv add geekflare-api python-decouple
Set your API key
GEEKFLARE_API_KEY=your_api_key_here
python-decouple reads from .env automatically. Add .env to .gitignore.
Service class
Keep all Geekflare logic in one place. Create services/geekflare.py in your app:
yourapp/services/geekflare.py
from decouple import config
from geekflare_api.client import GeekflareClient
from geekflare_api.models import WebScrapeDto, SearchDto, ScreenshotDto
from geekflare_api.exceptions import ApiException
class GeekflareService:
"""Thin wrapper around the Geekflare SDK for use in Django views."""
def __init__(self):
self._api_key = config("GEEKFLARE_API_KEY")
def _client(self) -> GeekflareClient:
return GeekflareClient(api_key=self._api_key)
def web_scrape(self, url: str, **kwargs) -> dict:
with self._client() as client:
return client.web_scrape(WebScrapeDto(url=url, **kwargs))
def search(self, query: str, **kwargs) -> dict:
with self._client() as client:
return client.search(SearchDto(query=query, **kwargs))
def screenshot(self, url: str, **kwargs) -> dict:
with self._client() as client:
return client.screenshot(ScreenshotDto(url=url, **kwargs))
# Module-level singleton — import this in your views
geekflare = GeekflareService()
Web Scraping
View
import json
from django.http import JsonResponse
from django.views import View
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
from geekflare_api.exceptions import ApiException
from .services.geekflare import geekflare
@method_decorator(csrf_exempt, name="dispatch")
class ScrapeView(View):
def post(self, request):
try:
body = json.loads(request.body)
except json.JSONDecodeError:
return JsonResponse({"error": "Invalid JSON"}, status=400)
url = body.get("url")
if not url:
return JsonResponse({"error": "url is required"}, status=400)
try:
result = geekflare.web_scrape(
url=url,
renderJS=body.get("renderJS", True),
blockAds=body.get("blockAds", True),
format=body.get("format", "html,markdown"),
)
return JsonResponse(result, safe=False)
except ApiException as e:
return JsonResponse(
{"error": e.reason, "code": e.status},
status=e.status or 500,
)
URL
from django.urls import path
from .views import ScrapeView
urlpatterns = [
path("scrape/", ScrapeView.as_view(), name="scrape"),
]
Test:
curl -X POST http://localhost:8000/scrape/ \
-H "Content-Type: application/json" \
-d '{ "url": "https://toscrape.com/" }'
Search
View
@method_decorator(csrf_exempt, name="dispatch")
class SearchView(View):
def post(self, request):
try:
body = json.loads(request.body)
except json.JSONDecodeError:
return JsonResponse({"error": "Invalid JSON"}, status=400)
query = body.get("query")
if not query:
return JsonResponse({"error": "query is required"}, status=400)
try:
result = geekflare.search(
query=query,
limit=body.get("limit", 10),
location=body.get("location", "us"),
source=body.get("source", "web"),
time=body.get("time"),
format="json",
)
return JsonResponse(result, safe=False)
except ApiException as e:
return JsonResponse(
{"error": e.reason, "code": e.status},
status=e.status or 500,
)
URL
from django.urls import path
from .views import ScrapeView, SearchView
urlpatterns = [
path("scrape/", ScrapeView.as_view(), name="scrape"),
path("search/", SearchView.as_view(), name="search"),
]
Test:
curl -X POST http://localhost:8000/search/ \
-H "Content-Type: application/json" \
-d '{ "query": "Django REST framework tutorial", "limit": 5 }'
Screenshot
View
@method_decorator(csrf_exempt, name="dispatch")
class ScreenshotView(View):
def post(self, request):
try:
body = json.loads(request.body)
except json.JSONDecodeError:
return JsonResponse({"error": "Invalid JSON"}, status=400)
url = body.get("url")
if not url:
return JsonResponse({"error": "url is required"}, status=400)
try:
result = geekflare.screenshot(
url=url,
type=body.get("type", "png"),
fullPage=body.get("fullPage", True),
device=body.get("device", "desktop"),
viewportWidth=body.get("viewportWidth", 1280),
viewportHeight=body.get("viewportHeight", 800),
blockAds=body.get("blockAds", True),
hideCookie=body.get("hideCookie", True),
quality=body.get("quality", 90),
)
return JsonResponse(result, safe=False)
except ApiException as e:
return JsonResponse(
{"error": e.reason, "code": e.status},
status=e.status or 500,
)
URL
from django.urls import path
from .views import ScrapeView, SearchView, ScreenshotView
urlpatterns = [
path("scrape/", ScrapeView.as_view(), name="scrape"),
path("search/", SearchView.as_view(), name="search"),
path("screenshot/", ScreenshotView.as_view(), name="screenshot"),
]
Test:
curl -X POST http://localhost:8000/screenshot/ \
-H "Content-Type: application/json" \
-d '{ "url": "https://example.com", "fullPage": true }'
Using Django REST Framework
If your project uses DRF, swap the class-based views for APIView:
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from geekflare_api.exceptions import ApiException
from .services.geekflare import geekflare
class ScrapeAPIView(APIView):
def post(self, request):
url = request.data.get("url")
if not url:
return Response({"error": "url is required"}, status=status.HTTP_400_BAD_REQUEST)
try:
result = geekflare.web_scrape(
url=url,
renderJS=request.data.get("renderJS", True),
blockAds=request.data.get("blockAds", True),
format=request.data.get("format", "html,markdown"),
)
return Response(result)
except ApiException as e:
return Response(
{"error": e.reason, "code": e.status},
status=e.status or status.HTTP_500_INTERNAL_SERVER_ERROR,
)
Error handling
The SDK raises ApiException with a status code and reason string on non-2xx responses.
from geekflare_api.exceptions import ApiException
try:
result = geekflare.web_scrape(url="https://toscrape.com/")
except ApiException as e:
if e.status == 401:
# Invalid or missing API key
elif e.status == 402:
# Credits exhausted — check dash.geekflare.com
elif e.status == 403:
# Endpoint not available on current plan
elif e.status == 429:
# Rate limit hit — implement exponential backoff
else:
# Unexpected error
raise
Common error codes
| Code | Meaning |
|---|
401 | Missing or invalid x-api-key |
402 | API credits exhausted |
403 | Endpoint requires a higher plan |
404 | Wrong endpoint URL or HTTP method |
429 | Rate limit exceeded |
Next steps