PHP printf / sprintf

Ma Mahalakshmi V Updated 14 Nov 2026
12 min read ·Lesson 16 of 256

What Are printf() and sprintf()?

In simple terms: printf() and sprintf() build text from a template that contains placeholders. Each placeholder is replaced by a value and can control how that value looks — how many decimal places, how wide the field is, whether it has leading zeros, and so on.

Technically: Both functions take a format string containing ordinary text and conversion specifications (starting with %), followed by the values to insert. They differ only in what they do with the result:

FunctionWhat It DoesReturns
printf()Outputs the formatted string directlyThe number of bytes output (int)
sprintf()Builds the formatted string without outputting itThe formatted string

Why They Exist

Simple interpolation ("Total: $total") inserts values exactly as they are. Real applications often need precise formatting:

  • Prices with exactly two decimals: 1499.50, not 1499.5
  • Invoice numbers with leading zeros: INV-000042
  • Aligned columns in reports, logs, and command-line output
  • Numbers in hexadecimal, binary, or scientific notation
  • Message templates where the text and the values are kept separate (useful for translations)

printf()-style formatting comes from the C programming language, so the same patterns are recognized by developers who use many other languages.


Basic Syntax

printf(string $format, mixed ...$values): int
sprintf(string $format, mixed ...$values): string

Example

<?php
$product = "Notebook";
$quantity = 3;
$price = 45.5;

printf("%s x %d = %.2f\n", $product, $quantity, $quantity * $price);

$line = sprintf("%s x %d = %.2f", $product, $quantity, $quantity * $price);
echo strtoupper($line) . "\n";

Output

Notebook x 3 = 136.50
NOTEBOOK X 3 = 136.50

How It Works

The format string "%s x %d = %.2f\n" contains three placeholders. They are filled in order by the arguments that follow:

PlaceholderValueMeaningResult
%s"Notebook"Insert as a stringNotebook
%d3Insert as an integer3
%.2f136.5Insert as a float with 2 decimals136.50
  • printf() prints the result immediately.
  • sprintf() returns the same text as a string, so it can be stored, modified (here with strtoupper()), passed to another function, saved to a database, or returned.

Use sprintf() when you need the text for further processing; use printf() when you only want to output it.


Structure of a Conversion Specification

Each placeholder follows this pattern:

%[argnum$][flags][width][.precision]specifier

Only % and the specifier are required. The optional parts must appear in this order.

PartPurposeExample
argnum$Choose which argument to use by position%2$s uses the second value
flagsPadding, alignment, and sign behavior-, +, 0, '*
widthMinimum number of characters%10s
.precisionDecimal places for floats; maximum length for strings%.2f, %.5s
specifierHow to interpret the values, d, f, x

The following sections explain each part, starting with specifiers.


Specifiers

SpecifierTreats the Value AsExampleOutput
sStringsprintf('%s', 'PHP')PHP
dSigned integersprintf('%d', 42.9)42
uUnsigned integersprintf('%u', 42)42
fFloat, locale-awaresprintf('%f', 3.14)3.140000
FFloat, not locale-awaresprintf('%.1F', 3.14)3.1
e / EScientific notationsprintf('%.2e', 12345.678)1.23e+4
g / GShorter of f or esprintf('%g', 0.00001234)1.234e-5
x / XHexadecimal (lowercase / uppercase)sprintf('%x', 255)ff
oOctalsprintf('%o', 8)10
bBinarysprintf('%b', 5)101
cCharacter with the given ASCII codesprintf('%c', 65)A
%A literal percent signsprintf('%d%%', 75)75%

Important Details

  • %d truncates floats. sprintf('%d', 42.9) produces 42, not 43. The value is converted to an integer, which removes the decimal part. Use %.0f or round() if you need rounding.
  • %f defaults to 6 decimal places. Always specify precision, such as %.2f, for readable output.
  • %f vs %F: %f respects the current locale's decimal separator (set with setlocale()), so in some locales it may output 3,14. %F always uses a dot. For output that will be parsed by machines — JSON, CSV, SQL, APIs — use %F.
  • %% is needed because a single % starts a placeholder.

Example: The Same Number in Different Formats

<?php
$number = 255;

printf("Decimal:     %d\n", $number);
printf("Hexadecimal: %x\n", $number);
printf("HEX (upper): %X\n", $number);
printf("Octal:       %o\n", $number);
printf("Binary:      %b\n", $number);
printf("Scientific:  %.2e\n", $number);

Output

Decimal:     255
Hexadecimal: ff
HEX (upper): FF
Octal:       377
Binary:      11111111
Scientific:  2.55e+2

Hexadecimal output is common when working with colors (#ff8800), hashes, and binary data. Note that PHP writes exponents without leading zeros (e+2), unlike some other languages that output e+02.


Precision

For Floats: Decimal Places

<?php
$pi = 3.14159265;

printf("%.0f\n", $pi);
printf("%.2f\n", $pi);
printf("%.4f\n", $pi);

Output

3
3.14
3.1416

Precision rounds the value to the requested number of decimals (3.14159 → 3.1416).

Note: Floats are stored in binary and cannot represent most decimal fractions exactly. A value written as 2.675 is actually stored as 2.67499999..., so rounding it to two places can produce a result that looks wrong. When exact decimal results matter (money, tax), work with integers (for example, amounts in paise or cents) or the BCMath extension. This is explained in PHP Floats.

For Strings: Maximum Length

<?php
$title = "Introduction to Object-Oriented PHP";

printf("%.15s...\n", $title);

Output

Introduction to...

For strings, precision cuts the string after the given number of characters. This is useful for previews and fixed-width columns.

Note: The cut counts bytes, not characters. For text containing multibyte characters (such as Tamil, Hindi, Chinese, or emoji), cutting by bytes can split a character and produce invalid output. Use mb_substr() or mb_strimwidth() for such text. See Multibyte Strings.


Width and Padding

Width sets the minimum number of characters a value occupies. If the value is shorter, it is padded; if it is longer, it is not truncated.

Example

<?php
printf("[%10s]\n", "PHP");    // right-aligned (default)
printf("[%-10s]\n", "PHP");   // left-aligned
printf("[%05d]\n", 42);       // zero-padded
printf("[%'*10s]\n", "PHP");  // custom padding character
printf("[%'.10d]\n", 42);     // dots as padding
printf("[%3s]\n", "Longer");  // value wider than width

Output

[       PHP]
[PHP       ]
[00042]
[*******PHP]
[........42]
[Longer]

Flags Explained

FlagEffect
(none)Pad with spaces on the left (right-align)
-Pad on the right (left-align)
0Pad numbers with zeros on the left
'charPad with any character, written after a single quote ('*, '., '_)
+Always show the sign of a number (+5, -5)

Width With Floats

For floats, the width includes the decimal point and the decimal places:

<?php
printf("[%8.2f]\n", 3.14159);
printf("[%08.2f]\n", 3.14159);

Output

[    3.14]
[00003.14]

3.14 is 4 characters, so 4 padding characters are added to reach a width of 8.

Showing the Sign

<?php
$changes = [12.5, -3.25, 0];

foreach ($changes as $change) {
    printf("%+.2f%%\n", $change);
}

Output

+12.50%
-3.25%
+0.00%

The + flag is useful for financial and statistical output, where showing the direction of change matters. Here, %% adds the percent sign after each value.


Argument Numbering (Swapping)

By default, placeholders consume arguments in order. Adding n$ after the % selects a specific argument, which allows reusing or reordering values.

Example

<?php
$name = "Anita";
$count = 3;

printf('%1$s, you have %2$d new messages. Check them, %1$s!' . "\n", $name, $count);

Output

Anita, you have 3 new messages. Check them, Anita!

Why Single Quotes Are Used

The format string uses single quotes so that PHP does not try to interpolate $s and $d as variables. In a double-quoted string, "%1$s" would trigger an attempt to read a variable named $s. If you need double quotes, escape the dollar sign: "%1\$s".

Why Argument Numbering Matters for Translation

Different languages place words in different orders. With numbered arguments, a translator can rearrange the sentence without changing the code:

<?php
$templates = [
    'en' => '%1$s ordered %2$d items.',
    'xx' => '%2$d items were ordered by %1$s.', // a language with different word order
];

foreach ($templates as $lang => $template) {
    echo sprintf($template, 'Kiran', 4) . "\n";
}

Output

Kiran ordered 4 items.
4 items were ordered by Kiran.

The arguments are always passed in the same order; only the template changes. Translation systems such as gettext rely on this.

Note: Do not mix numbered and unnumbered placeholders in one format string. Unnumbered placeholders after numbered ones can consume arguments in confusing ways.


FunctionDifference From sprintf() / printf()
vsprintf($format, $array)Takes the values as an array and returns a string
vprintf($format, $array)Takes the values as an array and outputs the result
fprintf($stream, $format, ...)Writes the result to a stream, such as a file or STDERR
sscanf($string, $format)The reverse: parses values out of a string using a format
number_format($num, $decimals)Formats numbers with thousands separators (which printf does not add)

Example: vsprintf() With an Array

<?php
$row = ['Laptop', 2, 54999.0];

echo vsprintf("%-10s %3d  %10.2f\n", $row);

Output

Laptop       2    54999.00

vsprintf() is convenient when the values already exist in an array, such as a row returned from a database.

Example: fprintf() to Standard Error

<?php
fprintf(STDERR, "Import failed at line %d: %s\n", 128, "invalid date");

In command-line scripts, writing errors to STDERR keeps them separate from normal output, so php import.php > result.txt still shows the error in the terminal.


Practical Example: A Formatted Receipt

<?php
$items = [
    ['name' => 'Wireless Mouse',      'qty' => 2, 'price' => 649.00],
    ['name' => 'Mechanical Keyboard', 'qty' => 1, 'price' => 3899.50],
    ['name' => 'Mouse Pad',           'qty' => 3, 'price' => 199.00],
];

$receiptNo = 731;
$lineWidth = 44;

printf("Receipt No: R-%06d\n", $receiptNo);
echo str_repeat('-', $lineWidth) . "\n";
printf("%-22s %4s %16s\n", 'Item', 'Qty', 'Amount');
echo str_repeat('-', $lineWidth) . "\n";

$total = 0;

foreach ($items as $item) {
    $amount = $item['qty'] * $item['price'];
    $total += $amount;

    printf("%-22.22s %4d %16s\n", $item['name'], $item['qty'], number_format($amount, 2));
}

echo str_repeat('-', $lineWidth) . "\n";
printf("%-27s %16s\n", 'TOTAL', number_format($total, 2));

Output

Receipt No: R-000731
--------------------------------------------
Item                    Qty           Amount
--------------------------------------------
Wireless Mouse            2         1,298.00
Mechanical Keyboard       1         3,899.50
Mouse Pad                 3           597.00
--------------------------------------------
TOTAL                               5,794.50

Step-by-Step Explanation

  1. R-%06d pads the receipt number with zeros to six digits (000731), producing consistent, sortable identifiers.
  2. str_repeat('-', $lineWidth) draws a separator line of a fixed length.
  3. %-22s left-aligns item names in a 22-character column; %4s and %16s right-align the other headers, so headers line up with the data below them.
  4. %-22.22s sets both width and precision to 22: short names are padded, and long names are cut so they never push the other columns out of alignment.
  5. number_format($amount, 2) adds thousands separators and two decimals. Its result is a string, so it is inserted with %16s (right-aligned) rather than %f, which cannot add separators.
  6. The TOTAL line uses a width of 27 (22 + 1 space + 4) for the label, so the amount aligns with the amount column above it.

Fixed-width formatting like this is used in command-line tools, log files, plain-text emails, and thermal receipt printers.


Practical Example: Building Strings for Later Use

<?php
function formatDuration(int $totalSeconds): string
{
    $hours = intdiv($totalSeconds, 3600);
    $minutes = intdiv($totalSeconds % 3600, 60);
    $seconds = $totalSeconds % 60;

    return sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds);
}

function slugWithId(string $title, int $id): string
{
    $slug = strtolower(trim(preg_replace('/[^a-z0-9]+/i', '-', $title), '-'));
    return sprintf('%s-%d', $slug, $id);
}

echo formatDuration(3725) . "\n";
echo formatDuration(59) . "\n";
echo slugWithId('PHP printf & sprintf Guide', 15) . "\n";

Output

01:02:05
00:00:59
php-printf-sprintf-guide-15

How It Works

  • intdiv() performs integer division; % gives the remainder. 3725 seconds = 1 hour, 2 minutes, 5 seconds.
  • %02d pads each part to two digits with zeros, giving a standard clock format.
  • In slugWithId(), sprintf('%s-%d', ...) combines a URL-friendly slug with a numeric ID. The regular expression replaces runs of non-alphanumeric characters with hyphens; regular expressions are covered in the PHP RegEx section.
  • Both functions return strings built with sprintf(). They do not print anything, so callers decide where the text goes: a page, a JSON response, or a database.

Errors in PHP 8

PHP 8 reports formatting mistakes with exceptions instead of silently returning false.

Too Few Arguments

<?php
printf("%s scored %d points", "Ravi");
PHP Fatal error:  Uncaught ArgumentCountError: 3 arguments are required, 2 given

The format has two placeholders, so it needs the format plus two values — three arguments in total.

A frequent cause is a percent sign that was meant to be literal. In printf("Progress: 50% done"), PHP reads % d (a space flag followed by the d specifier) as a placeholder that needs a value. Write 50%% done instead.

Extra Arguments

<?php
printf("%s\n", "Ravi", "unused");

Extra arguments are ignored without any error. This can hide mistakes, so check that the number of placeholders matches the values.

Unknown Specifier

<?php
printf("Progress: %z", 50);
PHP Fatal error:  Uncaught ValueError: Unknown format specifier "z"

PHP throws a ValueError when the character after % (and any flags, width, or precision) is not a valid specifier.


Common Mistakes

Using %d for Prices

Effect: Decimal parts disappear: %d of 99.99 prints 99.

Fix: Use %.2f, or number_format() for display.

Using Double Quotes With Numbered Arguments

Effect: "%1$s" tries to interpolate $s and produces a warning or wrong output.

Fix: Use single quotes, or escape the dollar: "%1\$s".

Forgetting to Escape %

Effect: ArgumentCountError, ValueError, or unexpected output.

Fix: Write %% for a literal percent sign.

Assuming Width Truncates

Effect: Long values push columns out of alignment.

Fix: Add precision for strings: %-20.20s.

Formatting Multibyte Text by Width

Effect: Columns misalign, because ₹ or é takes several bytes but displays as one character.

Fix: Pad multibyte text with mb_str_pad() (PHP 8.3+) or calculate padding with mb_strwidth().

Using %f for Machine-Readable Output

Effect: In some locales, %f produces 3,14, which breaks CSV files, SQL, and APIs.

Fix: Use %F for data meant for other programs.

Storing Money as Formatted Strings

Effect: Calculations on strings like "1,298.00" produce wrong results.

Fix: Keep numeric values for calculations and format only at the moment of display.


printf() Family vs Other Formatting Options

NeedBest Tool
Insert a value into text without formattingInterpolation: "Hello $name"
Fixed decimals, padding, alignment, number basessprintf() / printf()
Thousands separatorsnumber_format()
Locale-aware currency and numbers (₹1,00,000.00, 1.234,56 €)NumberFormatter from the intl extension
Dates and timesdate() or DateTime::format()

Best Practices

  • Use sprintf() in functions that return text and printf() only for direct output.
  • Always specify precision for floats (%.2f).
  • Use %F when output will be read by other programs.
  • Use numbered arguments (%1$s) in templates that may be translated, and write them in single quotes.
  • Format values only for display; keep raw numbers for calculations and storage.
  • Use mb_* functions for padding or cutting multibyte text.

Official reference: https://www.php.net/manual/en/function.sprintf.php

0 Comments

Reviewed before they appear

No comments yet.

PHP
PHP Tutorial Index PHP Home PHP Intro PHP Install PHP Built-in Web Server PHP Syntax PHP Tags PHP and HTML PHP Comments PHP Multiline Comments PHP Variables Variables Scope Static Variables Variable Variables PHP Echo / Print PHP printf / sprintf PHP Data Types PHP Booleans PHP NULL PHP Strings String Functions Modify Strings Concatenate Strings Slicing Strings Escape Characters String Interpolation Heredoc and Nowdoc Search in Strings Multibyte Strings PHP Floats PHP Casting PHP Type Juggling PHP Math PHP Random Numbers PHP Constants PHP Magic Constants PHP Operators Arithmetic Operators Assignment Operators Comparison Operators Increment / Decrement Operators Logical Operators Null Coalescing Operator Spaceship Operator Operator Precedence PHP If...Else...Elseif PHP If PHP If Operators PHP If...Else PHP Shorthand if PHP Nested if PHP Switch PHP Match Alternative Syntax PHP Loops While Loop Do While Loop For Loop Foreach Loop Nested Loops Break Statement Continue Statement PHP Functions User-defined Functions Function Arguments Default Argument Values Pass by Reference Named Arguments Variadic Functions Return Values Type Declarations in Functions Recursive Functions Variable Functions Anonymous Functions Closures Arrow Functions First-class Callable Syntax PHP Arrays Indexed Arrays Associative Arrays Create Arrays Access Array Items Update Array Items Add Array Items Remove Array Items Sorting Arrays Multidimensional Arrays Array Destructuring Array Spread Operator Search in Arrays Merge Arrays array_map / array_filter / array_reduce Array Functions PHP Superglobals $GLOBALS $_SERVER $_REQUEST $_POST $_GET $_FILES $_COOKIE $_SESSION \$\_ENV PHP RegEx RegEx Patterns RegEx Modifiers preg_match preg_replace preg_split PHP RegEx Functions PHP Form Handling PHP Form Validation PHP Form Required PHP Form URL/E-mail Form Input Sanitizing Escaping Output (htmlspecialchars) Checkbox, Radio and Select Inputs Sticky Forms PHP Form Complete PHP Date and Time Date Formatting DateTime Class Timezones PHP Include Include vs Require PHP File Handling PHP File Open/Read PHP File Create/Write File Delete / Rename / Copy PHP Directories PHP CSV Files PHP File Upload PHP Cookies PHP Sessions PHP Filters PHP Filters Advanced PHP Callback Functions PHP JSON PHP Exceptions Error Handling Custom Error Handler Error Logging HTTP Headers and Redirects Output Buffering Sending Email PHP cURL Consuming REST APIs PHP Generators PHP What is OOP PHP Classes/Objects The $this Keyword PHP Properties PHP Methods PHP Constructor Constructor Property Promotion PHP Destructor PHP Access Modifiers Readonly Properties PHP Inheritance Method Overriding The final Keyword PHP Class Constants PHP Abstract Classes PHP Interfaces Polymorphism PHP Traits PHP Static Methods PHP Static Properties Late Static Binding Magic Methods Object Cloning Comparing Objects Anonymous Classes PHP Enums PHP Namespaces Autoloading Classes PHP Iterables Iterators Object Serialization Strict Types Union Types Nullable Types Mixed and Never Types Nullsafe Operator PHP Attributes PHP Fibers Readonly Classes Property Hooks (PHP 8.4) Asymmetric Visibility (PHP 8.4) Reflection API SPL Data Structures MySQL Database MySQL Connect MySQL Create DB MySQL Create Table MySQL Insert Data MySQL Get Last ID MySQL Insert Multiple MySQL Prepared MySQL Select Data MySQL Where MySQL Order By MySQL Delete Data MySQL Update Data MySQL Limit Data MySQL Joins with PHP Pagination with PHP PDO Introduction PDO Connect PDO Prepared Statements PDO Fetch Modes PDO Transactions PDO Error Handling PHP XML Parsers PHP SimpleXML Parser PHP SimpleXML - Get PHP XML Expat Parser PHP DOM Parser PHP XMLReader PHP XMLWriter AJAX Intro AJAX PHP AJAX Database AJAX XML AJAX Live Search AJAX Poll AJAX with JSON Security Introduction Password Hashing SQL Injection Prevention XSS Prevention CSRF Protection Session Security Secure Cookies File Upload Security Filesystem Security Error Reporting in Production Hiding PHP Encryption with Sodium PHP Configuration (php.ini) PHP Command Line (CLI) Composer PSR-4 Autoloading Installing Extensions (PECL / PIE) Debugging PHP OPcache & Performance Garbage Collection PHP-FPM Migrating to PHP 8 Project: Contact Form with Email Project: Login & Registration System Project: CRUD App with MySQL Project: Image Upload Gallery Project: Shopping Cart with Sessions Project: Simple Blog Project: REST API with PHP
Ask about this post
AI Ask about this post

Ask questions about PHP printf / sprintf and get answers drawn from it.

Signed-in readers only.