sodcalculator

10 Tech How-To

Generate PDFs & Screenshots with Browser APIs

Guide 10-32554 · Updated · Step by step

This guide shows you how to use the built-in browser APIs to generate PDFs and capture screenshots directly from your web application. You’ll need a basic understanding of JavaScript and HTML, and a modern browser like Chrome, Edge, or Firefox. By the end, you’ll be able to add these features without any external libraries.

What You’ll Need

  • A modern web browser (Chrome, Edge, Firefox, or Safari).
  • A text editor or IDE for writing code.
  • Basic knowledge of HTML, CSS, and JavaScript.
  • For the screenshot part, a web page or local HTML file to test on.

Step-by-Step

Generating a PDF from HTML

  1. Create a basic HTML page with the content you want to export. For example, a simple invoice with a heading and a table.
  2. Add a button that will trigger the PDF generation. Give it an id like downloadPdf.
  3. In your JavaScript, get a reference to the element you want to print. Usually you’ll target the body or a specific container div.
  4. Use the window.print() method to open the browser’s print dialog. The user can then choose “Save as PDF” as the destination.
  5. To make the print output look good, add a @media print CSS block to hide buttons, navigation, and other non-essential elements.
  6. For more control (like generating a PDF without a dialog), you can use the window.print() with a hidden iframe. Create an iframe, copy the HTML into it, and call iframe.contentWindow.print().

Capturing a Screenshot with the Screen Capture API

  1. Check browser support for getDisplayMedia(). It works in Chrome, Edge, and Firefox, but not in Safari.
  2. Create a button with id startCapture and a video element where the stream will be displayed.
  3. Add a click event listener to the button. Inside the handler, call navigator.mediaDevices.getDisplayMedia().
  4. Pass the options object to the method: { video: { mediaSource: 'screen' } }. This tells the browser you want to capture the screen.
  5. Assign the returned stream to the video element: video.srcObject = stream. Then play the video.
  6. To take a snapshot, draw the video frame onto a canvas using canvas.drawImage(video, 0, 0, width, height).
  7. Convert the canvas to an image using canvas.toDataURL('image/png'). This gives you a base64 string that you can display or download.
  8. To download the image, create an <a> element with the href set to the data URL and the download attribute set to a filename. Click it programmatically.

Common Mistakes

  • Forgetting to stop the screen capture stream after taking a screenshot. This leaves the browser showing a “sharing” indicator and can drain resources.
  • Not handling the case where the user cancels the screen selection dialog. This throws an error, so you need a try...catch block.
  • Using window.print() without print CSS. The result often includes buttons, backgrounds, and layout issues.
  • Trying to capture a specific element with getDisplayMedia. This API captures the entire screen, or a window, not a single DOM element.
  • Calling getDisplayMedia() without user gesture. It must be called directly in a click handler or keypress event.

Tips

  • For PDF generation, consider using the @page CSS rule to set margins and page size.
  • Use page-break-inside: avoid on tables or images to prevent them from being split across pages.
  • For screenshots, you can capture a specific window by passing { video: { mediaSource: 'window' } } instead of 'screen'.
  • To capture a specific element (like a chart), use a library like html2canvas or dom-to-image. These are not browser APIs but are commonly used for that purpose.
  • Always stop the video stream when you’re done with it: stream.getTracks().forEach(track => track.stop()).
  • Test on different browsers because the Screen Capture API has varying levels of support.

Troubleshooting

  • Screenshot button does nothing: Check that you’re calling getDisplayMedia() inside a user gesture. Also, check the browser console for errors. If you’re on Safari, the API isn’t supported.
  • “Permission denied” error: The user may have denied the screen share request. You can’t force it, but you can show a friendly message asking them to retry and allow it.
  • The PDF looks unstyled: You likely forgot the @media print CSS. Add it and make sure your print styles are specific enough to override the screen styles.
  • The video element is black: This can happen if you try to draw the video to canvas before it has loaded. Wait for the loadedmetadata event on the video element before drawing.
  • The screenshot is blank: Make sure the video is actually playing and that the canvas dimensions match the video’s videoWidth and videoHeight.

Frequently Asked Questions

Can I generate a PDF without the print dialog?

No, the native window.print() method always shows a dialog. To generate a PDF silently, you’ll need to use a library like jsPDF or a server-side solution.

Can I capture a screenshot of a specific div?

Not with the native Screen Capture API. That API captures the whole screen or a window. To capture a specific element, you need a library like html2canvas.

Is the Screen Capture API available in Firefox?

Yes, Firefox supports getDisplayMedia() with the mediaSource: 'screen' option. However, the user still has to select what to share.

Can I capture audio along with the screen?

Yes, you can include audio by adding audio: true to the options object. But note that the user may be prompted to choose an audio source.

How do I stop the screen capture after taking a screenshot?

Call stream.getTracks().forEach(track => track.stop()) after you’ve drawn the frame to the canvas. This stops the sharing indicator.

Does window.print() work on mobile browsers?

Yes, mobile browsers support window.print(). On iOS Safari, it opens the print dialog where the user can choose “Save as PDF” or use AirPrint.

Related

General steps for current mainstream versions; menus can differ by device and version. See the disclaimer or report an error.

More in this bed

The whole Tech How-To bed →