Microlink API Examples for Capturing Full-Page Screenshots in Laravel
Capture a full-page screenshot with Microlink from Laravel. See runnable HTTP-client and cURL examples, response handling, options, troubleshooting, and a ScreenshotNeo alternative.
To capture an entire scrollable page with Microlink from Laravel, send the target address as url, set screenshot.fullPage to true, and read the resulting image URL from data.screenshot.url. Microlink is a regular HTTP API here; this example uses Laravel’s HTTP client, not a Microlink-specific Laravel SDK. The examples adapt Microlink’s documented parameters and Laravel’s HTTP client pattern; they are not claims of a live capture test. See the Microlink screenshot parameter reference, screenshot guide, and Laravel HTTP client documentation.
This answers the search “Microlink API examples for capturing full-page screenshots in Laravel”: full-page capture must be enabled explicitly. If omitted, screenshot capture defaults to the visible viewport. With Laravel’s nested query parameters, express the option as 'screenshot' => ['fullPage' => true].
1. Make a full-page screenshot request in Laravel
Laravel’s Http facade sends the request and encodes the query parameters. This example requests PNG output, disables metadata extraction because the application only needs the screenshot, checks for HTTP and API errors, then validates the image URL before using it.
<?php
use Illuminate\Support\Facades\Http;
use RuntimeException;
$targetUrl = 'https://example.com';
$response = Http::timeout(60)->get('https://api.microlink.io', [
'url' => $targetUrl,
'screenshot' => [
'fullPage' => true,
'type' => 'png',
],
'meta' => false,
]);
// Raise an exception for non-successful HTTP status codes.
$response->throw();
$payload = $response->json();
if (! is_array($payload) || ($payload['status'] ?? null) !== 'success') {
throw new RuntimeException('Microlink did not return a successful screenshot.');
}
$imageUrl = $payload['data']['screenshot']['url'] ?? null;
if (! is_string($imageUrl) || $imageUrl === '') {
throw new RuntimeException('Microlink response did not contain a screenshot URL.');
}
// Store or return $imageUrl as appropriate for your application.
The screenshot URL is hosted by the API response; the example returns or stores that URL rather than downloading the bytes into Laravel. The response’s screenshot object can also include values such as type, width, height, and size. If you need those details, retain them from $payload['data']['screenshot'].
Put the target URL in configuration
For application code, take the target URL from validated input or a trusted configuration source rather than hard-coding arbitrary user input. Laravel can return an image URL to a view or persist it for a later job. If user-submitted URLs are accepted, apply your application’s URL validation and outbound-request protections; a screenshot service request is still an operation initiated by your app.
2. Equivalent cURL request
The raw query convention uses dot notation, screenshot.fullPage=true. Use a query encoder when assembling a URL: the target URL may itself contain query parameters and must not be concatenated unescaped.
curl --get 'https://api.microlink.io' \
--data-urlencode 'url=https://example.com' \
--data-urlencode 'screenshot.fullPage=true' \
--data-urlencode 'screenshot.type=png' \
--data-urlencode 'meta=false'
For PHP code that builds the request URL, http_build_query can encode a flat parameter array:
<?php
$params = [
'url' => 'https://example.com',
'screenshot.fullPage' => 'true',
'screenshot.type' => 'png',
'meta' => 'false',
];
$requestUrl = 'https://api.microlink.io?' . http_build_query($params);
When using Laravel’s HTTP client, prefer the parameter array passed to Http::get(). If a custom client or encoder serializes nested arrays differently, check that the outgoing query represents the documented screenshot.fullPage=true option.
3. Read and use the API response
In JSON mode, the screenshot is represented in the response under data.screenshot. The URL for the image is data.screenshot.url. Check both the HTTP response and the API’s JSON status before using it; a successful transport alone does not guarantee the expected screenshot field exists.
{
"status": "success",
"data": {
"screenshot": {
"url": "https://...",
"type": "png",
"width": 1280,
"height": 2400,
"size": 123456
}
}
}
The URL and numeric values above illustrate the response shape; they are not a captured response or a measured result. Use the fields returned by the actual request. JSON mode is useful when your backend needs to inspect the result or its metadata. Microlink also documents an embed mode for cases where a direct image response or image URL is useful in markup; consult its guide for the current embed syntax.
4. Choose screenshot options for the page
| Option | When to use it | Notes |
|---|---|---|
screenshot.fullPage |
Capture the scrollable document rather than only the visible viewport. | Set to true; full-page capture is not the default. |
screenshot.type |
Choose the output image format. | PNG is the documented default. PNG and JPEG are supported; JPEG quality applies when JPEG is selected. |
screenshot.element |
Capture a particular component identified by a CSS selector. | This is a different capture target from a whole-page request. Use it when the desired output is a component, not the full document. |
meta |
Skip extracted page metadata when only the screenshot is needed. | Set false to avoid metadata extraction. Microlink describes this as usually the biggest speedup for screenshot-only requests, without promising a fixed latency improvement. |
| Shared wait controls | Allow dynamic page content to appear before capture. | Choose a documented wait condition or delay for the page’s rendering behavior; do not assume application-specific asynchronous content is ready automatically. |
Check the screenshot parameter reference and parameter documentation for current names and accepted values. The key distinction for this task is between full-page capture, which requests the whole scrollable page, and the default viewport capture.
Dynamic pages and lazy content
A page that fills in content after its initial load can be captured before the relevant content is ready unless an appropriate wait is configured. Microlink’s content-method reference describes shared wait controls. Select a wait suited to the page: a condition tied to a meaningful element is generally more targeted than an arbitrary delay, while a delay can be useful when the page has no reliable ready selector. A longer wait can increase request duration, so avoid waiting longer than the content needs.
5. Python and Node.js equivalents
These examples show the same REST request for teams that need to compare clients or move the capture logic outside Laravel. They expect JSON and extract the same screenshot URL.
Python with requests
import requests
response = requests.get(
"https://api.microlink.io",
params={
"url": "https://example.com",
"screenshot.fullPage": "true",
"screenshot.type": "png",
"meta": "false",
},
timeout=60,
)
response.raise_for_status()
payload = response.json()
if payload.get("status") != "success":
raise RuntimeError("Microlink did not return a successful screenshot.")
image_url = payload.get("data", {}).get("screenshot", {}).get("url")
if not isinstance(image_url, str) or not image_url:
raise RuntimeError("Microlink response did not contain a screenshot URL.")
print(image_url)
Node.js with built-in fetch
const params = new URLSearchParams({
url: 'https://example.com',
'screenshot.fullPage': 'true',
'screenshot.type': 'png',
meta: 'false',
});
const response = await fetch(`https://api.microlink.io?${params}`, {
signal: AbortSignal.timeout(60_000),
});
if (!response.ok) {
throw new Error(`Microlink HTTP error: ${response.status}`);
}
const payload = await response.json();
if (payload.status !== 'success') {
throw new Error('Microlink did not return a successful screenshot.');
}
const imageUrl = payload.data?.screenshot?.url;
if (typeof imageUrl !== 'string' || imageUrl.length === 0) {
throw new Error('Microlink response did not contain a screenshot URL.');
}
console.log(imageUrl);
6. Troubleshoot common problems
| Symptom | Likely cause | What to do |
|---|---|---|
| Only the top of the page appears | The request used the default viewport behavior or the full-page option was serialized incorrectly. | Set screenshot.fullPage=true. In Laravel, pass 'screenshot' => ['fullPage' => true]; inspect the encoded query if using a custom client. |
| There is no image URL in the response | The response may not have succeeded, or the response shape is not the one expected. | Call throw() for HTTP errors, inspect the JSON status, and check for data.screenshot.url before using it. |
| The image is missing content loaded by JavaScript | The page’s asynchronous rendering may finish after the capture. | Configure an appropriate shared wait condition or delay, then verify that the condition corresponds to the content you need. |
| The request times out | The target page or full-page rendering takes longer than the client timeout allows. | Set a reasonable client timeout for your workload, inspect whether the target is slow or unusually long, and avoid unbounded retries. A larger timeout does not fix a target that consistently fails to load. |
| The request URL breaks for pages with query strings | The target URL was concatenated into a raw query without encoding. | Pass a parameter array to Laravel’s client or use a query encoder such as cURL’s --data-urlencode or PHP’s http_build_query. |
| The returned image has the wrong format | The screenshot type was omitted or set to a different supported format. | Set screenshot.type to the desired documented format and handle JPEG quality only when requesting JPEG. |
| A full-page image is very tall or large | The page itself is long, so capturing its entire scrollable area produces a large image. | Consider whether a specific element capture is the actual need, or process/store the full-page asset appropriately. Do not switch to element capture if full-document coverage is required. |
7. Performance, reliability, and cost considerations
- Skip unused metadata. If only the screenshot is needed,
meta=falseavoids metadata extraction; Microlink says this is usually its largest speedup for screenshot-only requests, but the actual improvement varies. - Wait for the right condition. A targeted wait can avoid capturing before important content renders; unnecessary long waits increase request duration.
- Validate before persisting. Check the HTTP status, API status, and screenshot URL. This avoids treating an error payload as an image result.
- Use bounded timeouts and retries. Set a client timeout appropriate to your application and only retry transient failures under a bounded policy. Repeatedly retrying a deterministic target-page error adds load without making the capture more reliable.
- Account for vendor limits and changing plans. Microlink’s guide, accessed October 3, 2026, states that its API works without an API key and offers 25 free requests per day. The guide says production plans unlock options including configurable TTL, stale-while-revalidate caching, custom filenames, custom headers, and proxy. These are vendor-reported, time-sensitive details; check Microlink’s current guide and plan information before relying on them. No plan prices are stated here.
8. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server from ScreenshotNeo. A single GET request returns a screenshot or PDF; your Laravel application does not need to manage a browser for this capture. The request below saves the returned image bytes as a WebP file. See the ScreenshotNeo API documentation for request options.
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://example.com \
-o shot.webp
Laravel can make the same GET request and save its response body:
<?php
use Illuminate\Support\Facades\Http;
$response = Http::timeout(90)->get('https://api.screenshotneo.com/v1/shot', [
'access_key' => config('services.screenshotneo.key'),
'url' => 'https://example.com',
]);
$response->throw();
file_put_contents(storage_path('app/shot.webp'), $response->body());
- Cookie banners are accepted and removed before the shot, along with 60+ known consent platforms, newsletter popups, and chat widgets; each step can be turned off.
- Bot checks, blank pages, timeouts, failed loads, and cache hits are never billed. Response headers identify the page verdict and billing status.
- An MCP server provides
take_screenshot,get_page_info, andcapture_pdftools for Claude, Cursor, and other MCP clients. - 1,000 screenshots per month are free with no card. Paid plans start at $5 for 3,000 screenshots; all features are available on every plan.
Sign up free for 1,000 screenshots a month, with no card required.
9. Frequently asked questions
Does Laravel need a Microlink package?
No package is required for the documented approach. Laravel’s HTTP client can call the API directly; Microlink’s guide also says callers may use any HTTP client.
What does full-page mean here?
It requests a screenshot of the whole scrollable page. Without the option, the documented default is the visible viewport.
Can I get the image bytes instead of a hosted URL?
Microlink documents an embed mode for direct image responses or use in markup. Use JSON mode when you want to inspect the API status and screenshot metadata before passing the URL on.
Should I set meta=false?
Set it when your application only needs the screenshot. Leave metadata enabled if your workflow uses extracted page metadata.


