You wrote a meta description, watched the counter turn green at 155 characters, and published. The result that came back printed about 137 characters, stopped mid sentence, and the sentence was not the one you wrote.
The counter was measuring the wrong unit. A search result does not count characters. It fills a box of a fixed width in pixels with text in a specific font at a specific size, and stops when the box is full. In the font a desktop result uses for titles, Illinois, Mississippi, Tennessee is 32 characters and 273 px wide. WOMEN, WAX, WAVES AND MUSCLE is 28 characters and 356 px wide. The shorter string is 82 px wider. A character counter ranks those two the wrong way round.
That is the entire reason two SEO tools disagree about the same string. One divides by an average character width somebody wrote down years ago, the other measures the glyphs. And the counting problem is only half of it: the description you supply is a suggestion, not a promise, and an engine that does not like it will write its own from the page.
Below are the real box sizes, the places where WordPress adds characters you never typed, and a preview that measures rather than counts.
Fifty characters is not a measurement
A desktop result draws its title in 20px Arial. In that font a lowercase i advances 4.4 px and a capital W advances 18.9 px. Fifty lowercase i measure 222 px. Fifty capital W measure 944 px. Both strings are exactly fifty characters. The desktop title line is 600 px, so the first one fills a third of it and the second overflows it by more than half again.
Real titles never sit at those extremes, but they spread much further than most people assume. Capitals, W, M, m and a brand name with wide letterforms push a title right. Lowercase text full of i, l, t, f and r pulls it left. The title WordPress Image Sizes Explained: Every File Created From a Single Upload is 72 characters and measures 684 px, so a desktop result shows 58 of those characters and drops the last three words. A different 72 character title, written in lighter letters, comes in under 600 px and survives whole.
This is also why the “keep it under 60 characters” rule is folklore rather than a limit, in the same family as the other image SEO rules that people repeat without checking. Sixty is a rough average that happens to land near 600 px for ordinary English prose. It is a decent guess and a terrible measurement.
Where the string actually breaks
Paste in the title and description you intend to ship. The preview measures both with canvas text metrics in the same font and size a results page uses, 20px for a desktop title, 18px for a phone title and 14px for descriptions, then lays them out with greedy word wrap into the boxes each device gives and renders the truncated result line by line. What you see is what was measured, not a character count scaled by an average.
SERP and meta preview
Write a title and a description, and see what a results page would actually print. The text is measured with canvas metrics in the same font and size the results page uses, so the cut-off is a pixel width, not a character count. Everything happens in this browser tab: nothing is uploaded, and the social image is never fetched, only named.
A date in front of the description is Google's doing, not yours, and it eats into the same budget. Leave the field empty for a page that carries no date.
Desktop gives the title one line of 600 px and the description two. A phone gives the title two lines of 350 px and the description three. That is why a title is cut first on desktop and a description first on a phone.
The keyword is matched as plain text, upper and lower case alike.
It runs entirely in your browser. Nothing is uploaded, no request leaves the page, and the image address you type is never fetched, only shown by file name and written into the tags.
Four boxes, four budgets
A budget here is lines multiplied by line width, taken from the layout the results page draws, not from a character table. A desktop title gets one line of 600 px. A phone title gets two lines of 350 px, so 700 px in total. A desktop description gets two lines of 600 px, so 1200 px. A phone description gets three lines of 350 px, so 1050 px.
Read those four numbers together and a useful asymmetry falls out. The title budget is smaller on desktop than on a phone, because desktop only gives it one line. The description budget is larger on desktop than on a phone, because two long lines beat three short ones. So the same page loses its title on desktop first and its description on a phone first. Any tool that reports one number for “your snippet” is averaging two different failures.
The ragged right edge costs you characters
Total width is a lower bound, not the fit. Text is broken by greedy word wrap: fill the line with whole words, and when the next word does not fit, start a new line. Every line therefore ends somewhere short of the edge, and all of that leftover space is gone.
Take a 161 character description that measures 993 px at 14px Arial. On desktop it wraps to 563 px and 427 px across two lines and every character survives, with 211 px of the 1200 px budget wasted on the ragged edge. On a phone the same string wraps to 297 px, 335 px and 292 px, which is 924 px of the 1050 px available, and it still loses ten characters. The text is narrower than the budget and it is still cut, because 126 px of that budget sits at the ends of lines where no word fits.
The same effect explains the title example above. The desktop line holds 553 px of text and has 46 px of room left, but the next word, Single, is 56 px wide. Ten pixels short, and the reader sees a title that stops at “From a”.
The description is a suggestion, not a promise
WordPress core has never printed a meta description. There is no name="description" tag anywhere in wp-includes. Core produces a document title through wp_get_document_title() and nothing else, which means every description on your site is written by an SEO plugin from a field or a template.
Even once it is printed, the engine treats it as one candidate among several. It will write its own snippet when the description does not contain the words the searcher typed, when the same boilerplate description appears on dozens of your pages, when the description is a keyword list rather than a sentence, or when a passage on the page answers the query more directly. Long tail queries almost always get a generated snippet, because a single stored sentence cannot match every question a page answers.
Rank Math makes this explicit in the robots tag it emits by default, where the snippet length is declared unlimited:
<meta name="robots" content="index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1">
The value -1 means “no limit, take what you want”. If you want a hard ceiling you set max-snippet:160 and the engine will respect it, though what you usually get is a shorter snippet rather than your sentence. Individual passages can be excluded with the data-nosnippet attribute on a span, div or section. Neither of those makes your description appear. They only constrain what appears instead.
So the useful way to think about the description field: it is the snippet for the query you actually wrote it for, usually your brand name and your main term. Write it to be readable when it survives, and accept that a page ranking for forty queries will show forty different snippets.
What the title template adds behind your back
The string you type into the SEO title field is rarely the string that gets measured. Rank Math ships this as the default title template for posts and pages:
%title% %page% %sep% %sitename%
%sep% resolves to the separator picked once globally, from a short list that includes a hyphen, a pipe, a bullet, a right guillemet and two longer dash characters. %sitename% is the site title from Settings, General. %page% is empty on page one and becomes “Page 2” on a paginated archive, which is a length change you never see while editing.
Core does the same thing when a theme calls add_theme_support( 'title-tag' ). In wp-includes/general-template.php:
$sep = apply_filters( 'document_title_separator', '-' );
$title = implode( " $sep ", array_filter( $title ) );
The default separator is a plain hyphen, and the site name is appended as the last part on every view that is not the front page. Both are filterable, through document_title_separator and document_title_parts, and both have been there since WordPress 4.4.
Now the arithmetic. The suffix | WunderPaint is fourteen characters and 132 px at 20px, which is 22 per cent of the entire desktop title line. A separator plus a site name of ordinary length routinely takes a fifth of your budget before you have written a word. That is why the preview has a checkbox for a theme that appends the site name, with its own separator select, and why it warns when the title you typed already carries the site name: doubling it is common, and it costs you 44 characters of visible title.
Google also prefixes a date to the description on many results. Measured at 14px, a date prefix in the form the preview draws it costs 91 px, roughly fifteen characters of ordinary prose, taken off the front of a budget you had already spent.
Why the plugin preview and this tool disagree
Four separate reasons, and they compound.
- The unit. Rank Math counts characters. Its own SEO analyser cuts a description at 160 with
substrbefore scoring it. Yoast has measured the title in pixels for years, with a ceiling of 600, but still assesses the description by character count. Two plugins, three units. - Bytes are not characters. PHP’s
strlencounts bytes. A curly apostrophe is three bytes in UTF-8, an accented vowel is two, a non-breaking space is two. A description you consider 155 characters long can be 165 bytes long, and a byte based cut lands in a different place again. Pasted text from Word or a CMS is full of these, which is worth stripping before it reaches the field. - The font. A plugin preview inside wp-admin renders in the admin font stack at admin sizes. Even when it looks like a search result, it is not measuring Arial at 20px and 14px, so its line breaks are decorative.
- The string. The plugin expands the template, so it previews title plus separator plus site name. Paste only the title into an external tool and you have measured a shorter string than the one that ships.
The practical order: write the title in the plugin so the template variables resolve, copy the rendered result out of the plugin preview, and measure that string. The field content and the printed title are two different objects and only one of them is what a searcher sees.
The social card is a different measurement entirely
The same page has a second preview, and it obeys none of the rules above. A share card has no pixel budget you can measure from here, because each network truncates in its own font at its own size, and the card is dominated by the image rather than the text. What matters there is that the tags exist and are consistent.
The social section takes a social title and social description that fall back to the page title and meta description when left empty, the image address, an og:type and a twitter:card value, and writes a block you can paste: og:type, og:url, og:site_name, og:title, og:description, og:image with width and height for a large card, article:published_time when the type is article and a date is set, and the four twitter tags. Attribute values are escaped, so an ampersand or a quote in a title cannot break the markup.
Choosing summary instead of summary_large_image switches the preview to a 1:1 crop, which is the moment most people discover their card was designed for 1.91:1 and loses its text on the left and right. If that is where you land, the mechanics of which image WordPress actually hands to the network are worth reading, and the card layout itself is a separate problem.
Where the tool stops
The numbers are a facsimile of a moving target. Google changes its result layout without announcement, and a result carrying sitelinks, a star rating, a product row or a sitename breadcrumb variant will not match what you see here. The date prefix is drawn with a middle dot rather than the dash Google uses. Treat the pixel readout as a measurement of a model, accurate about the relative behaviour of two strings and approximate about the absolute cut.
Two smaller edges are worth knowing. A single word wider than the whole line is hard broken by binary search, and in that case the reported “cut after N characters” is off by the joins between lines. And whitespace is collapsed before measuring, exactly as a results page does, so double spaces and stray newlines in your description do not count against you here even though the field still stores them.
The tool also holds nothing. No storage, no upload, no state beyond the fields on screen, and one instance per page. Reload and it is empty again.
The unit that matters
Once you stop counting characters, the advice changes shape. There is no correct length for a title, only a width that fits the box you are aiming at, and the width depends on which letters you chose. A title in heavy capitals needs to be shorter than one in lowercase prose, and the only way to know by how much is to measure both. The same goes for the description, with the extra wrinkle that the phone cuts it before the desktop does, so the phone is the device you should be designing for.
The other half is accepting how little of this you control. You control the title almost completely, because the engine rarely rewrites a title that fits and matches the page. You control the description only for the queries it happens to answer. That asymmetry is a reason to spend your effort on the title, get the important words in front of the cut on both devices, and write the description as a clean sentence for your own brand query rather than as a keyword budget to be filled to 155.
Everything else is arithmetic you can do once. Work out what your template appends, subtract that width from the budget, and you know the real room you have to write in. Then measure the string, not the length of it.