Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
If Dompdf drops ğ, Ğ, ş, Ş, İ, ı, ö, Ö, ü, Ü, ç while the same HTML looks correct in a browser, the usual cause is the PDF font, not the Turkish text. Set Dompdf and your CSS to the bundled Unicode-capable DejaVu Sans, ensure the complete input pipeline is UTF-8, and render again. Use a readable TrueType font with @font-face only when you need different typography.
Why Turkish letters disappear in the PDF
Dompdf does not render a PDF with the same font stack your browser uses. Its core PDF fonts—Helvetica, Times, Courier, and the generic sans-serif, serif, and monospace families—use Windows ANSI coverage. That coverage is not a dependable source for every Turkish glyph. Dompdf maintainer Brian Sweeney describes those core fonts as supporting only Windows ANSI and advises styling text with a Unicode-capable font.
A browser can silently substitute a local font that contains the missing glyph. Dompdf instead resolves a glyph from the font selected for PDF generation. When that font has no character, the result can be a blank space, a box, or a question mark. A second, independent failure can occur earlier: a PHP string, template, or database value may already be mis-encoded before Dompdf receives it.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →The reliable baseline: UTF-8 plus DejaVu Sans
Dompdf bundles DejaVu TrueType fonts specifically to provide broad Unicode coverage by default. Make the choice explicit in both the Dompdf options and your stylesheet; that removes ambiguity from fallback resolution.
#1 Best Overall
Complete PHP example
<?php
require __DIR__ . '/vendor/autoload.php';
use DompdfDompdf;
use DompdfOptions;
$options = new Options();
$options->set('defaultFont', 'DejaVu Sans');
$dompdf = new Dompdf($options);
$html = <<<'HTML'
<!doctype html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<style>
body {
font-family: "DejaVu Sans", sans-serif;
font-size: 12pt;
}
</style>
</head>
<body>
<h1>Türkçe karakter testi</h1>
<p>ğ, Ğ, ş, Ş, İ, ı, ö, Ö, ü, Ü, ç, Ç</p>
</body>
</html>
HTML;
$dompdf->loadHtml($html, 'UTF-8');
$dompdf->setPaper('A4', 'portrait');
$dompdf->render();
$dompdf->stream('turkish-test.pdf', ['Attachment' => false]);
The meta declaration tells the HTML parser what the document contains. The explicit loadHtml($html, 'UTF-8') argument is useful when you know the string is UTF-8. Dompdf also examines a byte-order mark and meta declarations, and its loader can normalize non-UTF-8 input with mb_convert_encoding.
Apply the setting to your real template
Replace font declarations such as Arial, Helvetica, or a generic-only stack with "DejaVu Sans", sans-serif. Keep the UTF-8 declaration in the actual template that fails, not only in a test page. If different components specify their own font, update headings, table cells, labels, and generated fragments as well.
Verify encoding before Dompdf sees the HTML
- Test a literal string. Put
Türkçe: ğ Ğ ş Ş İ ı ö Ö ü Ü ç Çdirectly in the failing template. If literals work but database values do not, the fault is upstream. - Inspect the PHP value. Log or dump the string immediately before
loadHtml(). Mojibake such asÄŸindicates an earlier conversion problem, not a Dompdf font problem. - Check the database connection. Use a UTF-8-capable connection and confirm the table and column encoding. The exact database commands depend on your driver, but the invariant is that the bytes arriving in PHP must represent UTF-8 Turkish text.
- Declare UTF-8 in every generated document. Include
<meta charset="UTF-8">and pass the encoding toloadHtml()when known. - Confirm PHP MBString. Dompdf lists the MBString extension as a requirement and uses it when converting non-UTF-8 input. Install or enable it in the PHP runtime that runs your worker or web request, then restart that runtime.
Using a custom Turkish font
Choose a custom font when brand typography matters or when DejaVu Sans does not match your design. The file must be TrueType (.ttf), contain every Turkish glyph used, and be readable by the PHP process. Register it at runtime with CSS:
Recommended Free Tools
@font-face {
font-family: "Brand Turkish";
src: url("fonts/BrandTurkish-Regular.ttf") format("truetype");
font-style: normal;
font-weight: 400;
}
body {
font-family: "Brand Turkish", "DejaVu Sans", sans-serif;
}
File and cache requirements
- The URL in
srcmust resolve from the rendered HTML and stay inside Dompdf’s permitted file scope (its chroot or allowed path). - The font file and parent directories must be readable by the PHP user.
- Dompdf needs a writable font-cache location while it prepares metrics and cached files.
- Provide separate files for weights and styles you actually use. A regular face cannot reliably synthesize all bold or italic glyphs.
- After replacing a font, clear stale generated metrics when necessary and render a fresh PDF.
Use DejaVu Sans as a diagnostic baseline first. If Turkish text works with DejaVu but fails with the custom face, investigate the custom file, path, permissions, glyph coverage, and cache rather than changing the text.
A diagnostic sequence that isolates the fault
- Render the literal Turkish test string with DejaVu Sans and UTF-8 explicitly set.
- If it fails, verify the Dompdf installation and PHP MBString extension, then inspect the generated PDF itself.
- If it succeeds, substitute your real template data one source at a time: literal, PHP variable, database result, and final assembled HTML.
- Temporarily remove Arial, Helvetica, Times, Courier, and generic-only declarations so an inherited rule cannot override DejaVu Sans.
- For a custom font, verify the TrueType file path, chroot/allowed path, read permissions, glyph set, and writable cache.
- Open the PDF in a viewer and zoom into the exact characters. Browser success is not evidence that the PDF embedded or selected the same font.
Common symptoms, causes, and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| Only Turkish letters are boxes or question marks | Selected core PDF font lacks those glyphs | Set defaultFont and CSS to DejaVu Sans, or use a Unicode TrueType font. |
| Literal text works; database text is garbled | Encoding conversion before Dompdf | Inspect the PHP string and database connection; keep the entire path UTF-8. |
| Browser is correct; PDF is wrong | Browser substituted a local font | Inspect PDF font selection and explicitly set a Unicode-capable face. |
| Custom font is ignored | File outside allowed scope, unreadable, invalid URL, or stale metrics | Correct the path and permissions, confirm chroot access, clear metrics, and rerender. |
| Rendering fails after adding a font | Font cannot be read or cached | Use a readable TrueType file and make the font-cache directory writable. |
| Some weights lose characters | Missing bold or italic font face | Register the corresponding TrueType variants explicitly. |
Performance, reliability, and deployment notes
Bundled DejaVu avoids downloading a font at render time and is therefore a practical first choice for workers, containers, and restricted production environments. Custom fonts add an asset-management dependency: deploy the files with the application, preserve stable paths, and test permissions under the same PHP user as production.
Keep a small automated PDF test containing all characters your application promises to support. Test after Dompdf upgrades, PHP image/container changes, font replacements, and cache-directory changes. A successful HTML response is not enough; the assertion should inspect the generated PDF or a rendered page image for the actual glyphs.
Or skip the browser setup
If your next step is capturing a web page rather than generating a PDF with Dompdf, ScreenshotNeo provides a single screenshot API request. It accepts the cookie or consent banner before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be disabled. Only clean shots are billed: bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and the response identifies the result with X-Page-Verdict and X-Billed headers.
Read the parameter details in the ScreenshotNeo documentation. This cURL request returns a WebP file:
curl -G "https://api.screenshotneo.com/v1/shot"
-d access_key=YOUR_API_KEY
--data-urlencode url=https://stripe.com
-o shot.webp
The same endpoint from Python:
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
And from 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}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
ScreenshotNeo also offers an MCP server with take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. Every plan includes all features; 1,000 shots per month are free with no card, and paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account to get an API key.
FAQ
Do I need to convert Turkish letters to HTML entities?
No. Correct UTF-8 input and a font containing the glyphs are the durable solution. Entities cannot make a missing font glyph appear.
Rank #4
Is DejaVu Sans mandatory?
No. It is the simplest bundled baseline. Any accessible TrueType font with the required Turkish glyphs can work when registered correctly.
Why does changing only defaultFont sometimes not help?
A more specific CSS rule may still select another face. Set the font on the document elements and remove conflicting declarations while diagnosing.
Frequently Asked Questions
Can a PDF viewer be responsible for missing Turkish characters?
It is possible, but first verify the generated PDF with another viewer. If the same glyphs fail consistently, check Dompdf’s selected or embedded font and the source encoding.
Should I use a webfont URL in @font-face?
A local, readable TrueType file is more predictable. Remote or out-of-scope files can fail because Dompdf cannot access them under its allowed-path and network settings.
Quick Recap
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.

