Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Most often, this error is caused by an unquoted URL. If a value such as --header-html contains an ampersand (&), an unquoted shell command can split the URL before wkhtmltopdf receives it. Quote the complete value, then verify the installed version, option placement and final argument list produced by any wrapper.

The fastest fix: quote the complete URL

If your header, footer or input URL has query parameters, pass it as one argument:

# Preview Product Price
1 Image to PDF Converter Image to PDF Converter
wkhtmltopdf --header-html "https://example.test/header.php?id=123&mode=full" input.html output.pdf

The important detail is the pair of double quotes around the entire URL. In a POSIX shell, an unquoted & is a control operator. The shell can treat the text after it as a separate command or background the preceding command, so wkhtmltopdf sees incomplete or unexpected arguments. That can produce “Multiple Parameters Not Allowed,” even though the URL itself is valid.

This fix applies to the command shape documented for the reported case. It is not proof that every occurrence of the same message has the same cause. If quoting does not solve yours, use the diagnostic sequence below.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Image to PDF Converter
  • All item converter to pdf

What “multiple parameters” means in wkhtmltopdf

wkhtmltopdf does not reject every command containing multiple values. Its command synopsis is:

wkhtmltopdf [GLOBAL OPTION]... [OBJECT]... <output file>

An object is a webpage, a cover webpage or a table of contents. Several objects may be combined, in the order supplied. For example, a command can legitimately contain more than one input page:

wkhtmltopdf https://example.test/one https://example.test/two combined.pdf

The error usually means that one option received an unexpected extra token, or that a token intended to be part of a URL became a separate positional argument. Determine which of these layers is failing before removing options that are validly repeatable.

A reliable troubleshooting procedure

1. Record the executable and version

Run:

wkhtmltopdf --version

The commonly referenced usage text identifies wkhtmltopdf 0.12.6 with patched Qt, but distributions also ship other builds, including unpatched variants. Option behavior, available features and help text can differ. Keep the exact version, operating system and shell with your bug report.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

2. Inspect the real command, not only your source code

If PHP, Python, a job runner or a framework constructs the command, log the final argument vector passed to the process. A configuration object, a shell string and the eventual argv array are three different representations. A URL that looks correctly quoted in source may be split by an intermediate shell; conversely, quote characters inserted into an argument array may be passed literally to wkhtmltopdf.

3. Quote shell-significant values

Quote the whole value for URLs containing any of these characters:

  • ampersands (&) in query strings
  • spaces
  • parentheses
  • semicolons, pipes or redirection characters
  • shell expansion characters such as $, backticks or wildcards

For a URL, either single or double quotes can work in a POSIX shell, provided the chosen quote character does not occur unescaped inside the value:

wkhtmltopdf --header-html 'https://example.test/header.php?id=123&mode=full' input.html output.pdf

On Windows, use the quoting rules of the process launcher you are actually using. PowerShell, cmd.exe and a language API do not parse arguments identically.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

4. Verify option/value pairing

Options that take values must receive the intended value as the next argument. The official reference describes --cookie as taking a cookie name and value, and --custom-header as taking a header name and value. Both are repeatable, so multiple occurrences are legitimate:

wkhtmltopdf 
  --cookie session abc123 
  --cookie theme dark 
  --custom-header X-Request-Id 42 
  --custom-header X-Environment staging 
  input.html output.pdf

Do not “fix” the message by deleting valid repeated options. Instead, check whether a missing value shifted every later token one position to the left.

5. Check positional arguments

A normal invocation has global options, one or more document objects, and exactly one output filename. Look for:

  • an ampersand or space that split a URL into extra tokens
  • a duplicated input URL accidentally emitted by a loop
  • an output filename placed before the final input object
  • an empty variable expanding to an unexpected argument
  • literal quote characters in a value supplied through an argument array

Reduce the test to one input and one output:

wkhtmltopdf --header-html "https://example.test/header.php?id=123&mode=full" https://example.test/page.html test.pdf

If this works, add your other flags and objects back in small groups until the offending token is identified.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

6. Check scope and order

wkhtmltopdf distinguishes global options from page options. Global options belong before document objects. Page options can be used globally or in the page-option area permitted by the installed build. A syntactically valid flag in the wrong location may be interpreted as part of an object specification.

# Global option before objects
wkhtmltopdf --quiet page-one.html page-two.html merged.pdf

# Keep page-specific settings with the relevant page where supported
wkhtmltopdf page-one.html --cookie session abc123 page-two.html merged.pdf

Consult the help output from your own binary:

wkhtmltopdf --extended-help

Do not copy an option from a different package or version without checking that it exists and has the same scope.

Shell commands versus process APIs

PHP: prefer an argument array

When your PHP environment offers a process API that accepts an array of arguments, use it. Each array element becomes one argument, so an ampersand is data rather than shell syntax. The conceptual argument list is:

[
  'wkhtmltopdf',
  '--header-html',
  'https://example.test/header.php?id=123&mode=full',
  'input.html',
  'output.pdf'
]

Do not include the surrounding quote characters in the URL element. Quotes are needed only when a shell is parsing a command string. If you must build a shell string, escape each argument with the escaping function documented for your PHP version rather than concatenating user input.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Python: pass a list to the subprocess API

import subprocess

subprocess.run([
    "wkhtmltopdf",
    "--header-html",
    "https://example.test/header.php?id=123&mode=full",
    "input.html",
    "output.pdf",
], check=True)

With a list, Python does not invoke a shell by default. If you deliberately use shell=True, you have reintroduced shell parsing and must apply the shell’s quoting rules.

Node.js: pass an argv array

import { spawn } from "node:child_process";

const child = spawn("wkhtmltopdf", [
  "--header-html",
  "https://example.test/header.php?id=123&mode=full",
  "input.html",
  "output.pdf"
]);

child.on("close", (code) => {
  if (code !== 0) process.exit(code ?? 1);
});

As with Python, avoid a shell unless you specifically need shell features. Never add quote marks to an argv element merely because the equivalent command-line example shows them.

Headers, query strings and encoding details

There are two separate concerns:

  • Shell quoting: keeps characters such as & inside one argument.
  • URL encoding: represents reserved characters inside the URL itself.

Quoting does not URL-encode a value, and URL-encoding does not protect a shell command. If a query value contains a literal ampersand, it must be encoded as %26 for the URL’s meaning; separators between query parameters remain &. Then quote the complete resulting URL when invoking through a shell.

For a local header file, avoid a query string entirely when you do not need server-side parameters:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
wkhtmltopdf --header-html /absolute/path/header.html input.html output.pdf

Use an absolute path while diagnosing so that a changed working directory is not mistaken for a parameter error.

Common symptoms and targeted fixes

Symptom Likely cause Fix
Works without ?a=1&b=2, fails with it Unquoted ampersand split by the shell Quote the complete URL or pass an argv array
Adding a second cookie or header fails Missing name/value pair or wrapper serialized the option incorrectly Supply both values for every occurrence and inspect final argv
Command fails only in a framework Framework option mapping differs from shell syntax Follow that wrapper’s documented boolean and key/value representation
Minimal command works, full command fails One added flag, object or misplaced option is invalid Reintroduce arguments in small groups
Different machines disagree Different wkhtmltopdf builds, shells or patched-Qt packages Compare --version and help output on each machine
Quotes appear in the requested URL Literal quote characters were placed in an argv value Remove them; quote only at the shell layer

Wrapper-specific checks

Wrappers can fail before wkhtmltopdf starts. For example, django-wkhtmltopdf documents options as a mapping: simple flags can be represented by boolean values, while options requiring data use key/value entries. That representation is not the same as writing a shell command. Check the wrapper version and its generated command, and do not paste shell quotes into a mapping unless the wrapper explicitly expects them.

For security, keep URLs, headers, cookies and filenames separate from untrusted shell text. Prefer APIs that bypass a shell, restrict which executable is called, and log a sanitized argv list rather than credentials or session cookies.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Performance, reliability and cost considerations

Argument parsing is inexpensive; repeated retries usually are not. Capture stderr and the exit code, set an application timeout, and preserve the exact failing input for reproduction. A timeout or blank output is a different failure class from a parameter parse error. Test a static local HTML file first, then a simple remote page, then the header URL and optional flags.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When combining several objects, remember that each page can trigger network requests, JavaScript execution and asset loading. Keep the command minimal for diagnosis, then add objects deliberately. If a remote header endpoint depends on authentication, pass the required cookies or headers using the documented option pairs and ensure those values are not exposed in logs.

Or skip the browser setup

If your actual goal is a clean image or PDF of a URL rather than a wkhtmltopdf document pipeline, ScreenshotNeo provides a single HTTP request. It accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets; each step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers.

See the parameter reference and OpenAPI details in the ScreenshotNeo documentation. A cURL request is:

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

Python:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo also exposes an MCP server for Claude, Cursor and other MCP clients, with take_screenshot, get_page_info and capture_pdf tools. Other options include full-page captures with lazy images loaded, CSS-selector element capture, device presets and custom viewports, retina scale, PDF paper and page-range controls, custom CSS or JavaScript, click and wait actions, request blocking, headers, cookies, user agents, authorization, timezone and geolocation, transparent backgrounds, resizing, cache TTLs, signed image links, asynchronous webhooks, bulk capture of up to 100 URLs per call and a usage API. Every feature is on every plan. The Free plan includes 1,000 shots per month without a card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account to start.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When quoting is not enough

Collect these details before escalating:

  • the output of wkhtmltopdf --version
  • operating system and shell
  • the complete sanitized command or argv array
  • the wrapper or library name and version
  • the exact stderr text and exit code
  • whether the minimal one-page command succeeds

This information distinguishes shell parsing, wrapper serialization, option scope, unsupported features and genuine document-loading failures.

Practical checklist

  1. Run wkhtmltopdf --version.
  2. Capture the final argv passed to the process.
  3. Quote URLs containing ampersands when a shell is involved.
  4. Pass wrapper or language-process arguments as separate values.
  5. Verify every valued option has all required values.
  6. Keep global options before objects and page options in their documented scope.
  7. Test one input and one output, then add complexity gradually.
  8. Separate parse errors from timeouts, blank pages and network failures.

Frequently Asked Questions

Can wkhtmltopdf accept more than one input page?

Yes. Its object model permits several webpage, cover or table-of-contents objects in one output; the objects are processed in the order supplied.

Should I escape the ampersand as %26?

Only when the ampersand is literal data inside a query value. Parameter separators remain ampersands; shell quoting is still required when invoking through a shell.

Why did adding quotes in my Python list make the error worse?

An argv API does not need shell quotes. If you include them in the string, wkhtmltopdf receives the quote characters as part of the URL.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Is this error always caused by the shell?

No. The matching reported case was fixed by quoting, but wrappers, unsupported options, misplaced page settings and malformed option/value pairs can produce similar messages.

Quick Recap

Bestseller No. 1
Image to PDF Converter
Image to PDF Converter
All item converter to pdf

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.