ScreenshotNeo

BlogHow-to

How to Convert a URL to PDF with DocRaptor in Laravel

Convert a web page URL to a PDF in Laravel with DocRaptor’s PHP client. Learn setup, rendering options, downloads, storage, and common fixes.

By the ScreenshotNeo team4 October 20269 min read

To convert a URL to PDF with DocRaptor in Laravel, call DocRaptor’s PHP client from your server, pass the URL with setDocumentUrl(), and return or store the binary PDF response. Keep the API key in server-side configuration. DocRaptor must be able to retrieve the URL you submit.

This guide uses ordinary PHP client code inside a Laravel application. The official DocRaptor documentation covers its PHP client and API; the Laravel controller and storage examples below show how to handle that documented binary response in an application.

1. Install and configure the DocRaptor PHP client

Install the official package with Composer:

composer require docraptor/docraptor

Store the API key in your environment file, not in browser code or a committed source file:

DOCRAPTOR_API_KEY=your_api_key

Add a service entry in config/services.php:

'docraptor' => [
    'key' => env('DOCRAPTOR_API_KEY'),
],

After changing configuration in a deployed environment, refresh Laravel’s configuration cache as appropriate for that deployment. The DocRaptor API uses HTTP Basic Authentication with the API key as the username and an empty password; the PHP client example sets that username on DocApi. See the DocRaptor PHP documentation and API documentation.

2. Convert a URL and return a PDF download

Here is a complete controller method. It validates the submitted URL, asks DocRaptor for a PDF in test mode, and returns the binary payload as a download. Replace the validation policy with the hosts and URL rules appropriate for your application.

<?php

namespace App\\Http\\Controllers;

use DocRaptor\\ApiException;
use DocRaptor\\Doc;
use DocRaptor\\DocApi;
use Illuminate\\Http\\Request;
use Illuminate\\Support\\Facades\\Log;
use Throwable;

class PdfController extends Controller
{
    public function download(Request $request)
    {
        $validated = $request->validate([
            'url' => ['required', 'url', 'max:2048'],
        ]);

        $url = $validated['url'];

        $api = new DocApi();
        $api->getConfig()->setUsername(config('services.docraptor.key'));

        $doc = new Doc();
        $doc->setTest(true); // Test output is watermarked.
        $doc->setDocumentType('pdf');
        $doc->setDocumentUrl($url);

        try {
            $pdf = $api->createDoc($doc); // Binary string on success.
        } catch (ApiException $e) {
            Log::error('DocRaptor PDF generation failed', [
                'code' => $e->getCode(),
                'message' => $e->getMessage(),
                'response_body' => $e->getResponseBody(),
            ]);

            abort(502, 'The PDF could not be generated. Please try again later.');
        } catch (Throwable $e) {
            Log::error('Unexpected PDF generation error', [
                'message' => $e->getMessage(),
            ]);

            abort(502, 'The PDF could not be generated. Please try again later.');
        }

        return response($pdf, 200, [
            'Content-Type' => 'application/pdf',
            'Content-Disposition' => 'attachment; filename="page.pdf"',
        ]);
    }
}

Register a route to the controller, for example:

use App\\Http\\Controllers\\PdfController;
use Illuminate\\Support\\Facades\\Route;

Route::post('/pdf/download', [PdfController::class, 'download'])
    ->name('pdf.download');

Call this route from a form or application client that sends a url field. The code uses Laravel validation and response helpers for illustration; adapt authentication, authorization, rate limiting, and error handling to your app.

3. Store the generated PDF instead of downloading it

createDoc() returns binary document data on success. For storage, pass that string directly to Laravel’s storage disk; do not treat it as UTF-8 text or encode it as JSON.

use Illuminate\\Support\\Facades\\Storage;

$path = 'generated/' . uniqid('page-', true) . '.pdf';
Storage::disk('local')->put($path, $pdf);

return response()->json([
    'path' => $path,
]);

Choose the disk and access policy deliberately. A local private disk is suitable when the PDF should remain private; use a configured object-storage disk when the application’s delivery requirements call for it. The example’s storage handling is Laravel-side implementation guidance, while DocRaptor’s documented success response is binary PDF data.

4. URL input or HTML content?

Input Use it when Considerations
document_url The page already exists at a URL that DocRaptor can retrieve. The URL must be reachable from DocRaptor. Check that the page’s assets and any required rendering behavior are available to the renderer.
document_content Your Laravel application has already rendered the HTML and you want to send that content to DocRaptor. Relative asset paths need a base URL or an HTML <base> element so the renderer can resolve them.

The PHP client exposes URL input with setDocumentUrl($url). DocRaptor also accepts document content as an alternative input. The sources do not provide a recipe for authenticating DocRaptor to private Laravel routes, so do not assume a local or protected URL will be fetchable. For private content, evaluate an approved input and access design for your application.

5. Choose rendering settings

Test mode and production mode

Use setTest(true) while developing. Test PDFs are watermarked, and DocRaptor’s API reference says test documents do not count against monthly limits. Set test mode off for production output, subject to your account configuration.

Print media is the default. If the generated PDF looks different from the page as viewed in a browser, inspect the page’s print styles first. You can choose screen media through prince_options[media] when browser-like screen styles are more appropriate. See the API parameter reference.

JavaScript-dependent pages

DocRaptor’s PHP documentation says, “JavaScript is disabled by default.” Enable JavaScript when the source page needs it. For charts or content loaded from external data, rendering may finish before that content appears; the documentation recommends an explicit delay in such cases. Do not assume enabling JavaScript alone guarantees that every asynchronous page will be complete.

Relative assets with HTML input

When sending HTML rather than a URL, paths such as /css/report.css or images/logo.png need a base location. Configure a base URL or include an HTML <base> element; otherwise, the renderer may not find the stylesheets, images, or fonts.

6. Synchronous response or asynchronous generation?

The synchronous createDoc() flow returns the PDF bytes in the request. It fits a user-triggered download when generation completes within the request and response time your app can support. Longer conversions can tie up a web request and may run into application or proxy time limits.

DocRaptor also supports asynchronous generation. The API returns a status identifier and supports callbacks for successful completion. Generation errors do not invoke the callback, so your application still needs to check status and handle errors. Choose asynchronous processing when the user can wait for a later result or when a background workflow is a better fit; the sources do not prescribe one mode for every application.

7. cURL, Python, and Node.js reference calls

These examples show the API’s URL-to-PDF request outside Laravel. Keep the API key server-side in each environment. A successful direct API response contains binary PDF data; an error can be an XML body, so check the response status and content before saving it with a .pdf extension.

cURL

curl --user 'YOUR_API_KEY:' \\
  --header 'Content-Type: application/json' \\
  --data '{"document_url":"https://example.com/","name":"example","type":"pdf","test":true}' \\
  --output example.pdf \\
  https://docraptor.com/docs

Python

import requests

api_key = "YOUR_API_KEY"
payload = {
    "document_url": "https://example.com/",
    "name": "example",
    "type": "pdf",
    "test": True,
}

response = requests.post(
    "https://docraptor.com/docs",
    auth=(api_key, ""),
    json=payload,
    timeout=120,
)
response.raise_for_status()

content_type = response.headers.get("Content-Type", "")
if "pdf" not in content_type.lower():
    raise RuntimeError(f"Expected PDF response, got {content_type!r}")

with open("example.pdf", "wb") as output:
    output.write(response.content)

Node.js

const apiKey = process.env.DOCRAPTOR_API_KEY;
if (!apiKey) throw new Error('Set DOCRAPTOR_API_KEY');

const basic = Buffer.from(`${apiKey}:`).toString('base64');
const response = await fetch('https://docraptor.com/docs', {
  method: 'POST',
  headers: {
    'Authorization': `Basic ${basic}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    document_url: 'https://example.com/',
    name: 'example',
    type: 'pdf',
    test: true,
  }),
});

if (!response.ok) {
  const errorBody = await response.text();
  throw new Error(`DocRaptor returned ${response.status}: ${errorBody}`);
}

const bytes = Buffer.from(await response.arrayBuffer());
await (await import('node:fs/promises')).writeFile('example.pdf', bytes);

The cURL, Python, and Node.js snippets use the documented API endpoint and HTTP Basic authentication convention. They are reference calls for comparison with the PHP client; Laravel applications can use the PHP flow above.

8. Troubleshooting

Symptom Likely cause What to check or change
DocRaptor cannot download the URL The URL is unavailable to the renderer, invalid, or access controlled. Confirm the exact URL is reachable as required by your setup. A URL conversion requires DocRaptor to retrieve that URL; the reviewed docs do not establish a private-route authentication method.
The client reports an API exception The API request failed, and the response may contain an error document rather than PDF bytes. Inspect the exception code and response body in protected server logs. Return a generic application error to users and never log or expose the API key.
The saved file is not a PDF An error response was saved as if it were a successful binary document. Only save the returned bytes after createDoc() succeeds. For raw HTTP calls, check status and response content type before writing the file.
PDF is watermarked The request is still in test mode. Keep test mode for development; disable it for production output when your account is configured for production.
Styles differ from the browser page Print media is active by default, or print-specific CSS changes the layout. Review print styles or select screen media using the supported Prince option.
Charts or dynamic content are missing JavaScript is disabled by default, or rendering finished before asynchronous content loaded. Enable JavaScript when needed and configure an explicit delay for content that needs more time, as applicable.
Images, fonts, or CSS are missing from HTML input Relative URLs have no base location. Set a base URL or add an HTML <base> element and ensure referenced assets can be fetched.
Laravel request times out PDF generation took longer than the request or infrastructure timeout allows. Review request and proxy time limits. Consider DocRaptor’s asynchronous flow for conversions that should complete outside the user’s request.
API key appears unset Environment configuration is missing or Laravel is using cached configuration. Verify the server environment and services.docraptor.key configuration, then refresh the configuration cache according to your deployment process.

9. Performance, reliability, and cost considerations

  • Request duration: Synchronous generation keeps the caller waiting for the conversion. Use asynchronous generation where that wait does not fit the request path, and handle status checks as well as successful callbacks.
  • Page dependencies: JavaScript execution, delayed content, and external assets can affect both completion time and output. Keep the source page’s rendering needs in mind when choosing URL versus HTML input.
  • Binary handling: PDF bytes can be large. Return them directly for a download or write them to storage without text conversion. Avoid buffering or duplicating large payloads unnecessarily in your own application.
  • Failure handling: Treat a successful PDF response and an API error as different outcomes. Log useful exception diagnostics with access controls, and show users a non-sensitive error.
  • Cost: Test documents do not count against monthly limits according to DocRaptor’s API reference. Production pricing and limits can change; consult DocRaptor’s current account and pricing information rather than relying on figures copied into an integration guide.

Or skip the browser setup

If the job is to capture a page as a screenshot rather than generate a paginated PDF, ScreenshotNeo provides a website screenshot API and MCP server. Its one-call API returns PNG, JPEG, WebP, or PDF output; see the ScreenshotNeo API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

ScreenshotNeo accepts cookie and consent banners before capture and removes more than 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 cost nothing, and response headers say which page verdict applied and whether the request was billed. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots.

Sign up for ScreenshotNeo’s free plan: 1,000 screenshots a month, no card required.

FAQ

Does DocRaptor accept a URL for PDF generation?

Yes. The API accepts document_url, and the PHP client provides setDocumentUrl(). DocRaptor must be able to retrieve the submitted URL.

Can I generate the PDF from HTML produced by Laravel?

Yes. The API also accepts document content. When the HTML uses relative resource paths, provide a base URL so those resources can resolve.

Can I use test mode in production?

Test mode is intended for development checks and produces watermarked documents. Use non-test mode for production PDFs when your account is configured for it.

Where should the API key live?

Keep it in server-side configuration or a secret manager. Do not embed it in JavaScript or other publicly accessible website code.