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

PhantomJS renders Hebrew correctly only when three layers agree: a usable Hebrew font is available to the PhantomJS process, the document declares right-to-left language and direction, and the shaping engine can position every mark used by the text. A missing glyph, an unsuitable fallback, or incorrect bidirectional (bidi) metadata can produce boxes, reversed punctuation, or misplaced vowel points even when the page looks fine in a normal browser.

Fix those layers in that order, then verify the actual PNG or PDF produced in the same runtime image used in production.

What must be true before PhantomJS can draw Hebrew

  • The font exists in the runtime. Installing a typeface on your workstation does not install it in a container, CI runner, or server where PhantomJS runs.
  • The font covers the exact characters. Check base letters, punctuation, Hebrew presentation forms if your content uses them, and niqqud (vowel points) or cantillation marks when applicable.
  • The browser knows the text direction. Hebrew runs are right-to-left (RTL). Mixed Hebrew, Latin, numbers, and punctuation need explicit bidi context so the shaping engine can order each run correctly.
  • Glyph positioning works at the final size. OpenType Hebrew shaping includes mark reordering and mark-to-base positioning. A font can contain a glyph while still placing a mark badly.

Fontconfig supplies system-wide font configuration and application access. Its matcher selects the closest available pattern; a successful match does not prove that the chosen family resembles the requested font or covers every character your page contains.

Build a minimal Hebrew test page first

Before changing PhantomJS options, isolate the page and test the exact strings that fail. Include unvocalized and vocalized samples, mixed-direction text, punctuation, and numbers.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
<!doctype html>
<html lang="he" dir="rtl">
<head>
  <meta charset="utf-8">
  <style>
    @font-face {
      font-family: "AppHebrew";
      src: local("AppHebrew"), local("Noto Sans Hebrew");
    }
    body { font-family: "AppHebrew", sans-serif; font-size: 32px; }
    .mixed { direction: rtl; unicode-bidi: plaintext; }
    .latin { direction: ltr; unicode-bidi: isolate; }
  </style>
</head>
<body>
  <p>שלום עולם</p>
  <p>שָׁלוֹם עוֹלָם</p>
  <p class="mixed">גרסה 2.1 — example.com</p>
  <p>English ליד עברית 123</p>
</body>
</html>

Use lang="he" on the document or component that owns the Hebrew. Add dir="rtl" at the same scope, then override genuinely left-to-right fragments such as a URL, a code sample, or an account number. Inspect the screenshot, not only the DOM: bidi errors often appear only in punctuation and number ordering.

Make the font available to PhantomJS

Confirm the requested family in the runtime image

Run your font checks inside the same operating-system image, user account, and container that launches PhantomJS. Font files on a developer laptop are irrelevant if the capture worker uses a clean image. Verify the family name used in CSS, then verify that the file actually contains the Hebrew characters and marks in your test page.

System fonts and web fonts

A system-installed font is straightforward when you control the capture image and need deterministic startup. A web-delivered font can keep the application bundle self-contained, but PhantomJS must successfully load it before rendering and the font license must permit server-side use. Whichever method you choose, compare the produced screenshot with the target platform; neither delivery method guarantees correct glyph coverage or mark placement by itself.

Linux installation report: treat it as a lead, not a universal recipe

A 2017 PhantomJS issue comment reports that copying TTF files into /usr/share/fonts/truetype and running fc-cache -fv made the font available for one Linux PDF case. Distribution package names, font directories, permissions, and container layouts differ, and that report concerns selectable PDF text rather than a universal screenshot guarantee. Test the equivalent procedure against your exact Linux image:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
sudo install -m 0644 MyHebrewFont.ttf /usr/share/fonts/truetype/
sudo fc-cache -fv
fc-match "My Hebrew Family"
fc-query MyHebrewFont.ttf

If fc-match returns another family, the requested name may be wrong, the cache may not include the directory, or the font may not be installed for the account running PhantomJS. In an unprivileged container, install into a user font directory supported by that image and refresh the cache there.

Set direction and mixed-script boundaries explicitly

Document-level RTL

For a Hebrew-first page, use both language and direction metadata:

<html lang="he" dir="rtl">

For a component embedded in an otherwise LTR application, put dir="rtl" on the component instead of flipping the whole page. Mark embedded Latin fragments with dir="ltr" and an appropriate unicode-bidi value. Do not try to repair bidi output by reversing strings in JavaScript; that corrupts logical text and punctuation.

Mixed text, punctuation, and numbers

Test strings containing a Hebrew phrase followed by a colon, an English domain, a version number, and a dash. Assign direction to each semantic run. A screenshot in which letters look correct but the URL or number is reversed is a bidi-boundary problem, not a missing-font problem.

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

Handle niqqud and cantillation marks

Vowel points (niqqud), cantillation marks, and other combining characters are separate from base letters. OpenType Hebrew shaping reorders marks and positions them relative to the base glyph. Therefore:

  • Confirm the chosen font contains the marks used by your content.
  • Render vocalized samples at the actual production font size and device scale.
  • Look for marks that disappear, collide, or drift to a neighboring letter.
  • Compare a second known Hebrew-capable font to distinguish bad font data from a renderer limitation.

Increasing font-size temporarily can reveal an overlap, but it does not fix incorrect shaping. PDF paper dimensions, margins, orientation, and headers affect page layout; they do not add missing glyphs or repair bidi behavior.

Capture a controlled PhantomJS screenshot

Use a deterministic viewport, wait for the page to finish loading, and render only after your Hebrew test is visible. The following script is intentionally simple so a font or direction failure is easy to reproduce.

// capture.js
var page = require('webpage').create();
page.viewportSize = { width: 1280, height: 900 };
page.settings.resourceTimeout = 30000;
page.onResourceError = function (error) {
  console.log('Resource error: ' + error.url + ' :: ' + error.errorString);
};
page.onConsoleMessage = function (message) {
  console.log('console: ' + message);
};
page.open('https://your-site.example/hebrew-test', function (status) {
  if (status !== 'success') {
    console.log('Open failed: ' + status);
    phantom.exit(1);
    return;
  }
  window.setTimeout(function () {
    page.render('hebrew.png');
    phantom.exit(0);
  }, 1500);
});

The delay is a practical fallback for pages that load CSS or fonts asynchronously; choose a value appropriate to your application and verify it does not merely hide an intermittent failure. Log resource errors so a blocked stylesheet or font request is not mistaken for a shaping defect.

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

Keep output settings separate from text diagnostics

Changing paperSize, margins, orientation, or page ranges can alter where text appears in a PDF, but those settings do not make PhantomJS discover a font. Diagnose glyphs and bidi in a PNG first, then tune PDF pagination.

Troubleshooting by symptom

Boxes, blank glyphs, or a visibly unrelated typeface

  • Cause: The family is absent, the CSS name does not match the internal family name, or fallback lacks Hebrew coverage.
  • Fix: Check the runtime font inventory and fc-match result, install a Hebrew-capable font in that image, refresh the cache, and rerun the minimal page.

Hebrew letters appear but punctuation or numbers are backwards

  • Cause: Mixed-direction runs have no explicit boundaries.
  • Fix: Set lang="he" and dir="rtl" for Hebrew content; isolate URLs, code, and numeric identifiers with LTR direction and test the exact string.

Vowel points are missing or misplaced

  • Cause: The font lacks the combining marks, or mark-to-base positioning is not producing a usable result.
  • Fix: Verify mark coverage, compare another Hebrew font, and inspect at final size. Do not assume that visible base letters prove full Hebrew support.

The font works locally but not in CI or a container

  • Cause: Different image, user, cache, permissions, or network policy.
  • Fix: Install and cache the font during image creation, run the font query as the PhantomJS user, and make the test page report failed font or stylesheet requests.

Intermittent failures or an old WebKit rendering difference

  • Cause: The capture starts before resources settle, or PhantomJS’s old engine handles a page differently from current browsers.
  • Fix: Use a bounded wait, resource logging, and a small regression image set. If the project is new, reconsider the renderer: the PhantomJS GitHub repository is archived and read-only, with GitHub listing May 30, 2023 as the archive date.

A repeatable validation checklist

  1. Build the exact runtime image and install the intended Hebrew font there.
  2. Confirm the CSS family name and fontconfig match from the PhantomJS account.
  3. Check base letters, niqqud, cantillation, punctuation, Latin text, and numbers.
  4. Set language and direction metadata at document and component boundaries.
  5. Capture a PNG at production viewport and device scale.
  6. Inspect the image for fallback, bidi ordering, and mark placement.
  7. Only after text is correct, configure PDF dimensions and pagination.
  8. Keep a small Hebrew screenshot regression set for image or renderer upgrades.

Or skip the browser setup

ScreenshotNeo provides a website screenshot API and MCP server when maintaining a PhantomJS font environment is unnecessary. 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. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP tools—take_screenshot, get_page_info, and capture_pdf—work with Claude, Cursor, and other MCP clients.

One request returns PNG, JPEG, WebP, or PDF. The service supports full-page lazy-image loading, CSS-selector element capture, dark mode, device presets or custom viewports, retina scale, PDF paper and page options, custom CSS and JavaScript, clicks, waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, chosen-TTL caching, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API, an OpenAPI specification, and familiar screenshot-API parameter names.

See the ScreenshotNeo API documentation for authentication and options. Example cURL:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://your-site.example/hebrew-test -o shot.webp

Python:

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

Node.js:

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

The Free plan includes 1,000 screenshots each month without a card. Paid plans start at $5 for 3,000 screenshots; yearly billing provides two months free, and every feature is on every plan. Create a free ScreenshotNeo account to try it.

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

Frequently asked questions

Can a PDF setting fix missing Hebrew letters?

No. Paper size and margins control layout. Font availability, glyph coverage, and shaping must be corrected in the page and runtime.

Should I reverse Hebrew strings before capture?

No. Keep text in logical Unicode order and use HTML language, direction, and bidi boundaries.

Is the reported Linux font-copy workaround guaranteed?

No. It is a 2017 issue comment describing one Linux PDF case. Validate the equivalent installation and cache refresh on your distribution and image.

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

Is PhantomJS a good foundation for a new capture service?

Its archived, read-only repository is a maintenance warning. For an existing job, stabilize and test it; for new work, evaluate a maintained renderer or an API that removes browser-environment management.

Best Value

Frequently Asked Questions

Can a PDF setting fix missing Hebrew letters?

No. Paper size and margins control layout. Font availability, glyph coverage, and shaping must be corrected in the page and runtime.

Should I reverse Hebrew strings before capture?

No. Keep text in logical Unicode order and use HTML language, direction, and bidi boundaries.

Is the reported Linux font-copy workaround guaranteed?

No. It is a 2017 issue comment describing one Linux PDF case. Validate the equivalent installation and cache refresh on your distribution and image.

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

Is PhantomJS a good foundation for a new capture service?

Its archived, read-only repository is a maintenance warning. For an existing job, stabilize and test it; for new work, evaluate a maintained renderer or an API that removes browser-environment management.

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.