ScreenshotNeo

BlogHow-to

How to use PDFCrowd in a Laravel app to convert a URL to PDF

Convert a reachable URL to PDF in Laravel with PDFCrowd’s PHP client. Configure credentials, return a download response, and handle common errors safely.

By the ScreenshotNeo team4 October 20266 min read

Use PDFCrowd’s PHP client in a Laravel route or controller: install pdfcrowd/pdfcrowd, read the account username and API key from configuration, call convertUrl($url), and return the resulting bytes with Content-Type: application/pdf. The URL and its assets must be reachable from PDFCrowd’s servers. The examples below use a POST route because the conversion may take time and the URL should be validated before use.

1. Install the PHP client and configure credentials

From your Laravel project root, install the Composer package:

composer require pdfcrowd/pdfcrowd

Keep the PDFCrowd username and API key in environment-backed configuration rather than in source code. Add the following to config/services.php:

'pdfcrowd' => [
    'username' => env('PDFCROWD_USERNAME'),
    'api_key' => env('PDFCROWD_API_KEY'),
],

Set the values in your deployment environment or local .env file:

PDFCROWD_USERNAME=your_pdfcrowd_username
PDFCROWD_API_KEY=your_pdfcrowd_api_key

Do not commit real credentials. After changing configuration in an environment that caches Laravel config, refresh that cache as part of deployment.

2. Add a URL-to-PDF route

This minimal route validates the submitted URL, calls PDFCrowd, and sends the PDF as a download. Put it in routes/web.php if it is part of a browser-facing Laravel app. A production endpoint should also have appropriate authentication, authorization, and rate limiting for its users.

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Route;

Route::post('/pdf', function (Request $request) {
    $validated = $request->validate([
        'url' => ['required', 'url', 'max:2048'],
    ]);

    $url = $validated['url'];

    try {
        $client = new \Pdfcrowd\HtmlToPdfClient(
            config('services.pdfcrowd.username'),
            config('services.pdfcrowd.api_key')
        );

        $pdf = $client->convertUrl($url);

        return response($pdf, 200, [
            'Content-Type' => 'application/pdf',
            'Content-Disposition' => 'attachment; filename="document.pdf"',
            'Cache-Control' => 'no-cache',
            'Accept-Ranges' => 'none',
        ]);
    } catch (\Pdfcrowd\Error $error) {
        Log::error('PDFCrowd URL conversion failed', [
            'status' => $error->getStatusCode(),
            'reason_code' => $error->getReasonCode(),
            'message' => $error->getMessage(),
        ]);

        return response('PDF conversion failed.', 502);
    }
});

PDFCrowd’s Laravel example uses a POST route and returns the PDF bytes with the PDF content type, download disposition, Cache-Control: no-cache, and Accept-Ranges: none. The configuration keys, request validation, logging, filename, and generic error response here are Laravel integration choices. The client error provides status, reason code, message, and a documentation link; log diagnostics for operators while keeping credentials and raw vendor details out of public responses.

3. Ensure the converter can reach the page

convertUrl($url) makes the conversion service fetch the page. The supplied URL and any assets the page needs must be accessible from PDFCrowd’s servers. A URL such as http://localhost:8000 points to the converter’s own environment, not your development machine, so it cannot be used as an ordinary URL input.

  • For a public page, provide its reachable HTTPS URL.
  • For a page behind authentication, configure the source page’s required headers or cookies separately from the PDFCrowd API credentials.
  • For private or locally generated content, use the client’s HTML conversion methods or upload HTML instead of asking the remote service to fetch an inaccessible URL.
  • For HTML with relative assets, use absolute asset URLs or a suitable <base href="https://…">. An archive can be appropriate when the HTML and its assets need to travel together.

The PDFCrowd username and API key authenticate the conversion request; they do not automatically log the converter into the site being rendered. Review the PDFCrowd PHP client documentation for supported conversion methods and source-page options.

4. Choose memory or file output

convertUrl($url) returns PDF bytes in memory, which works well for a direct download. If the application needs a persistent local artifact, the PHP client also provides convertUrlToFile($url, $path):

$client = new \Pdfcrowd\HtmlToPdfClient(
    config('services.pdfcrowd.username'),
    config('services.pdfcrowd.api_key')
);

$client->convertUrlToFile($url, storage_path('app/reports/document.pdf'));

For a user download from storage, use Laravel’s file download response after verifying the path and access permissions. Avoid using a user-controlled filename or path directly.

5. Handle production traffic deliberately

A synchronous conversion keeps the integration simple, but the user’s HTTP request remains open while the remote conversion runs. For long conversions or workflows that create many PDFs, dispatch a Laravel queued job and notify the user when the artifact is ready. Queueing is an application architecture choice, not a requirement imposed by PDFCrowd.

  • Set application and proxy timeouts to accommodate the conversions your workflow permits; avoid retrying blindly when a client request times out, because the remote operation may already have completed.
  • Use bounded retries for transient failures, and make repeated jobs safe to run without creating unwanted duplicate records or notifications.
  • Limit which URLs users can submit. URL fetching can expose internal services if arbitrary private or loopback addresses are accepted. Enforce an allowlist or reject private and local destinations when the use case permits.
  • Keep generated files in controlled storage, authorize downloads, and remove temporary artifacts according to your retention needs.
  • Monitor conversion failures using the vendor error status and reason code. Do not log API keys, authorization headers, or sensitive page contents.

6. Troubleshooting

Symptom Likely cause What to do
Conversion cannot load the page The URL is local, private, blocked, or otherwise unreachable from the remote converter. Use a publicly reachable URL, or send HTML through a supported HTML input method.
Images or styles are missing Assets use relative paths, require a browser session, or cannot be reached by the converter. Use absolute or base-relative URLs and ensure assets are accessible; supply required source-site authentication where supported.
Authentication error from PDFCrowd The account username or API key is absent, incorrect, or not loaded from Laravel config. Check deployment environment values and the configured keys; refresh Laravel’s cached configuration after changing them.
PDF conversion returns an error The remote service rejected the request or encountered a conversion problem. Inspect the logged status and reason code and follow the client error’s documentation link. Return a controlled error to the caller.
Browser receives a broken or downloaded text response The response was not sent as PDF bytes or the content type/disposition is wrong. Return the byte string from convertUrl with application/pdf and a suitable Content-Disposition.
Laravel or proxy times out Conversion takes longer than the synchronous request’s timeout budget. Review relevant timeout settings or move conversion into a queue and deliver the completed file asynchronously.

7. Performance, reliability, and cost

Each synchronous request depends on your Laravel app reaching PDFCrowd and the converter reaching the target page and its assets. Network latency, source-page load time, and conversion time all affect how quickly a download is returned. Returning bytes in memory is straightforward, while file output and queued jobs can suit workflows that need persistence or longer processing.

Use retries selectively: a timeout does not always prove that the conversion failed, and a repeated request can consume another service operation. Record enough diagnostic information to investigate errors without retaining secrets. PDFCrowd pricing and current account terms are not established by the sources used for this guide, so check the vendor’s current plan details before estimating conversion costs.

Or skip the browser setup

If your goal is a screenshot of a page rather than a PDF document, ScreenshotNeo provides a website screenshot API and MCP server. Its GET endpoint returns PNG, JPEG, WebP, or PDF; one call can create a PDF:

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

See the ScreenshotNeo API documentation for request options. Cookie banners, popups, and chat widgets are removed before the shot; bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000. Sign up for free and get 1,000 screenshots a month with no card.

FAQ

Can I use this with Laravel’s API routes?

Yes. The conversion code can live in a controller used by an API route. Return the PDF response directly, or store it and return an authorized download URL if the API workflow is asynchronous.

Does a successful HTTP response guarantee every page element rendered?

No. The remote converter must load the page and its resources, and site behavior or access restrictions can affect what appears. Check the generated PDF with representative pages and ensure required resources are reachable.

Can I use this for a page that only exists in my local development environment?

Not by passing localhost as a URL to the remote service. Use an HTML input method or make the page reachable to the converter through an appropriate development setup.

References