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.
Laravel’s first-party HTTP client wraps Guzzle with a fluent, expressive API. This guide creates a dedicated GeekflareService, registers it in the service container, and injects it into controllers.
Prerequisites
Installation
No extra packages needed — Laravel’s HTTP client is built in. Just add your key to .env:
GEEKFLARE_API_KEY=your_api_key_here
.env is gitignored by default in Laravel. Use .env.example (without real
values) for documentation.
Config file
Centralise the API settings in a config file so they’re accessible via config():
<?php
return [
'api_key' => env('GEEKFLARE_API_KEY'),
'base_url' => 'https://api.geekflare.com',
];
Service class
app/Services/GeekflareService.php
<?php
namespace App\Services;
use Illuminate\Http\Client\PendingRequest;
use Illuminate\Http\Client\RequestException;
use Illuminate\Support\Facades\Http;
class GeekflareService
{
private PendingRequest $http;
public function __construct()
{
$this->http = Http::baseUrl(config('geekflare.base_url'))
->withHeaders([
'x-api-key' => config('geekflare.api_key'),
])
->acceptJson();
}
/**
* Scrape web page content.
*/
public function webScrape(array $params): array
{
return $this->post('/webscraping', $params);
}
/**
* Perform a web search.
*/
public function search(array $params): array
{
return $this->post('/search', $params);
}
/**
* Take a screenshot of a URL.
*/
public function screenshot(array $params): array
{
return $this->post('/screenshot', $params);
}
private function post(string $endpoint, array $params): array
{
$response = $this->http->post($endpoint, $params);
$response->throw(); // throws RequestException on 4xx/5xx
return $response->json();
}
}
Register in the service container
app/Providers/AppServiceProvider.php
<?php
namespace App\Providers;
use App\Services\GeekflareService;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->app->singleton(GeekflareService::class);
}
}
Web Scraping
Controller
app/Http/Controllers/ScrapeController.php
<?php
namespace App\Http\Controllers;
use App\Services\GeekflareService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Client\RequestException;
class ScrapeController extends Controller
{
public function __construct(
private readonly GeekflareService $geekflare
) {}
public function __invoke(Request $request): JsonResponse
{
$validated = $request->validate([
'url' => 'required|url',
'renderJS' => 'boolean',
'blockAds' => 'boolean',
'format' => 'string',
]);
try {
$result = $this->geekflare->webScrape([
'url' => $validated['url'],
'renderJS' => $validated['renderJS'] ?? true,
'blockAds' => $validated['blockAds'] ?? true,
'format' => $validated['format'] ?? 'html,markdown',
'device' => 'desktop',
]);
return response()->json($result);
} catch (RequestException $e) {
return $this->handleApiException($e);
}
}
private function handleApiException(RequestException $e): JsonResponse
{
$code = $e->response->status();
$body = $e->response->json();
return response()->json(
['error' => $body['message'] ?? 'API request failed', 'code' => $code],
$code
);
}
}
Route
use App\Http\Controllers\ScrapeController;
Route::post('/scrape', ScrapeController::class);
Test:
curl -X POST http://localhost:8000/api/scrape \
-H "Content-Type: application/json" \
-d '{ "url": "https://toscrape.com/", "renderJS": true }'
Search
Controller
app/Http/Controllers/SearchController.php
<?php
namespace App\Http\Controllers;
use App\Services\GeekflareService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Client\RequestException;
class SearchController extends Controller
{
public function __construct(
private readonly GeekflareService $geekflare
) {}
public function __invoke(Request $request): JsonResponse
{
$validated = $request->validate([
'query' => 'required|string',
'limit' => 'integer|min:1|max:100',
'location' => 'string|size:2',
'source' => 'string',
'time' => 'string|in:d,w,m',
'includeDomains' => 'array',
'excludeDomains' => 'array',
]);
try {
$result = $this->geekflare->search(array_merge(
['limit' => 10, 'location' => 'us', 'source' => 'web', 'format' => 'json'],
$validated
));
return response()->json($result);
} catch (RequestException $e) {
$code = $e->response->status();
$body = $e->response->json();
return response()->json(['error' => $body['message'] ?? 'Search failed'], $code);
}
}
}
Route
use App\Http\Controllers\SearchController;
Route::post('/search', SearchController::class);
Test:
curl -X POST http://localhost:8000/api/search \
-H "Content-Type: application/json" \
-d '{ "query": "Laravel best practices", "limit": 5 }'
Screenshot
Controller
app/Http/Controllers/ScreenshotController.php
<?php
namespace App\Http\Controllers;
use App\Services\GeekflareService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Client\RequestException;
class ScreenshotController extends Controller
{
public function __construct(
private readonly GeekflareService $geekflare
) {}
public function __invoke(Request $request): JsonResponse
{
$validated = $request->validate([
'url' => 'required|url',
'type' => 'string|in:png,jpg,webp',
'fullPage' => 'boolean',
'device' => 'string|in:desktop,mobile',
'viewportWidth' => 'integer',
'viewportHeight' => 'integer',
'blockAds' => 'boolean',
'hideCookie' => 'boolean',
'quality' => 'integer|min:1|max:100',
]);
try {
$result = $this->geekflare->screenshot(array_merge([
'type' => 'png',
'fullPage' => true,
'device' => 'desktop',
'viewportWidth' => 1280,
'viewportHeight' => 800,
'blockAds' => true,
'hideCookie' => true,
'quality' => 90,
], $validated));
return response()->json($result);
} catch (RequestException $e) {
$code = $e->response->status();
$body = $e->response->json();
return response()->json(['error' => $body['message'] ?? 'Screenshot failed'], $code);
}
}
}
Route
use App\Http\Controllers\ScreenshotController;
Route::post('/screenshot', ScreenshotController::class);
Test:
curl -X POST http://localhost:8000/api/screenshot \
-H "Content-Type: application/json" \
-d '{ "url": "https://example.com", "fullPage": true }'
All routes together
<?php
use App\Http\Controllers\ScrapeController;
use App\Http\Controllers\SearchController;
use App\Http\Controllers\ScreenshotController;
Route::post('/scrape', ScrapeController::class);
Route::post('/search', SearchController::class);
Route::post('/screenshot', ScreenshotController::class);
Error handling
Laravel’s HTTP client throw() converts 4xx/5xx responses to RequestException. Handle them by status code:
use Illuminate\Http\Client\RequestException;
try {
$result = $this->geekflare->webScrape(['url' => 'https://toscrape.com/']);
} catch (RequestException $e) {
$code = $e->response->status();
match ($code) {
401 => abort(401, 'Invalid or missing Geekflare API key.'),
402 => abort(402, 'API credits exhausted.'),
403 => abort(403, 'This endpoint requires a higher plan.'),
429 => abort(429, 'Rate limit exceeded. Try again shortly.'),
default => abort($code, $e->response->json('message') ?? 'API error'),
};
}
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