---
title: Print
description: A library that provides printing functionality for Android and iOS (AirPrint).
sourceCodeUrl: https://github.com/expo/expo/tree/sdk-52/packages/expo-print
packageName: expo-print
iconUrl: /static/images/packages/expo-print.png
platforms: ["android", "ios", "web"]
---
`expo-print` provides an API for Android and iOS (AirPrint) printing functionality.
## Installation
## Usage
```jsx
const html = `
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />
</head>
<body style="text-align: center;">
<h1 style="font-size: 50px; font-family: Helvetica Neue; font-weight: normal;">
Hello Expo!
</h1>
<img
src="https://d30j33t1r58ioz.cloudfront.net/static/guides/sdk.png"
style="width: 90vw;" />
</body>
</html>
`;
const [selectedPrinter, setSelectedPrinter] = useState();
const print = async () => {
// On iOS/android prints the given html. On web prints the HTML from the current page.
/* @info */ await Print.printAsync({
html,
printerUrl: selectedPrinter?.url, // iOS only
}); /* @end */
};
const printToFile = async () => {
// On iOS/android prints the given html. On web prints the HTML from the current page.
/* @info */ const { uri } = await Print.printToFileAsync({ html }); /* @end */
console.log('File has been saved to:', uri);
await shareAsync(uri, { UTI: '.pdf', mimeType: 'application/pdf' });
};
const selectPrinter = async () => {
/* @info */ const printer = await Print.selectPrinterAsync(); // iOS only
/* @end */
setSelectedPrinter(printer);
};
return (
<View style={styles.container}>
{Platform.OS === 'ios' && (
<>
{selectedPrinter ? (
<Text style={styles.printer}>{`Selected printer: ${selectedPrinter.name}`}</Text>
) : undefined}
</>
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#ecf0f1',
flexDirection: 'column',
padding: 8,
},
spacer: {
height: 8,
},
printer: {
textAlign: 'center',
},
});
```
## API
```js
```
## Local images
On iOS, printing from HTML source doesn't support local asset URLs (due to `WKWebView` limitations). Instead, images need to be converted to base64 and inlined into the HTML.
```tsx Example
const IMAGE = Asset.fromModule(require('@/assets/images/icon.png'));
const context = useImageManipulator(IMAGE.uri);
useEffect(() => {
async function generateAndPrint() {
try {
await IMAGE.downloadAsync();
const manipulatedImage = await context.renderAsync();
const result = await manipulatedImage.saveAsync({ base64: true });
const html = `
<html>
<img
src="data:image/png;base64,${result.base64}"
style="width: 90vw;" />
</html>
`;
await printAsync({ html });
} catch (error) {
console.error('Error:', error);
}
}
generateAndPrint();
}, [context]);
return <>{/* Render UI */}</>;
}
```
## Page margins
**On iOS** you can set the page margins using the `margins` option:
```js
const { uri } = await Print.printToFileAsync({
html: 'This page is printed with margins',
margins: {
left: 20,
top: 50,
right: 20,
bottom: 100,
},
});
```
If `useMarkupFormatter` is set to `true`, setting margins may cause a blank page to appear at the end of your printout. To prevent this, make sure your HTML string is a well-formed document, including `<!DOCTYPE html>` at the beginning of the string.
**On Android**, if you're using `html` option in `printAsync` or `printToFileAsync`, the resulting print might contain page margins (it depends on the WebView engine).
They are set by `@page` style block and you can override them in your HTML code:
```html
<style>
@page {
margin: 20px;
}
</style>
```
See [`@page` documentation on MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/@page) for more details.