Every product keeps people waiting. A dashboard pulls its numbers, an upload grinds through a large file, a search runs against a table that is having a slow day. Loading state copy is the small text you show in that gap, and most teams treat it as leftover work: a bare spinner, the word Loading with three dots, a progress bar with nothing written near it. The wait is the one moment you have someone's full attention and nothing for them to look at. What you write there decides whether the pause reads as handled or as broken.
This post is about what to say while someone waits. Not how to make the wait shorter, which matters more and is a different job, but the words for the seconds you cannot engineer away. We will work through skeleton screens, the progress message, and the slow connection case, and then look at what MicroKopy's own generator produces for the copy that sits at the edges of a wait, with a character count on every line. For the wider set of copy types this is one corner of, there is the pillar on how to write microcopy in UI.
Match the message to the length of the wait
Before you write a word, decide how long the wait actually is, because the right copy for a half-second pause and a thirty-second export are not the same copy. The usual reference here is Jakob Nielsen's three response-time limits, published by the Nielsen Norman Group and steady for decades: roughly a tenth of a second feels instant, about one second keeps a person in their flow of thought, and around ten seconds is the limit of held attention. Past that, minds wander, and the work has to tell the user it is still happening.
Those limits map cleanly onto what the copy has to do.
- Under a second. Say nothing. Text that flashes up and vanishes is noise, and a word nobody can finish reading is worse than a quiet spinner.
- One to ten seconds. A spinner or a skeleton carries the moment on its own. If you add text, add a label, not a sentence.
- Over ten seconds. Now the copy earns its place. Name what is happening, show progress if you honestly can, and set an expectation for how long is left.
- Over a minute, or anything a user might walk away from. Stop blocking the screen. Let them leave and tell them when it is done, which is where a notification takes over from the spinner.
A skeleton screen rarely needs words
A skeleton screen is the grey scaffolding that stands in for content before it arrives: blocked-out cards, lines where text will land, a circle where an avatar will be. Its whole trick is that it implies structure, so the page feels like it is assembling rather than hanging. That is also why skeleton screen text is usually a mistake. Drop the word Loading across the top of a skeleton and you undo the illusion, because you have just told the user that the thing they are looking at is fake.
When a skeleton does need a word, keep it to a quiet label tied to the region, not a status for the whole page. A reports panel can say Loading reports under its own heading while the rest of the screen stays live and usable. The test is simple. If the copy would read oddly after the content loads, it probably should not be there during the load either.
Progress message copy, when the spinner is not enough
Once a wait runs long enough to need words, a spinner stops being honest on its own. A circle that turns for thirty seconds tells the user nothing about whether they are two seconds or two minutes from done. This is where progress message copy does real work, and the rule is to say what is happening in terms the user recognises.
Name the step. "Compressing 12 of 40 files" tells someone more than "Please wait" ever will, and it quietly reassures them that the count is moving. Where you can show a real count or percentage, show it. Where you cannot, a plain statement of the current stage still beats a vague one: Checking your file, then Uploading, then Almost there reads as a process with an end.
Two things to avoid. Do not fake the progress bar. A bar that races to ninety percent and then sits there burns trust the first time someone notices, and they always notice. And do not promise a number you cannot keep. "This will take about 10 seconds" is a fine thing to write only when it is roughly true. If it is a guess, write "Just a moment" and leave the number out.
The slow connection message
Some waits are not your fault, and the copy should say so without making it the user's fault either. A slow connection message is what you show when the hold-up is the network rather than your server. The job is to separate three states that a bare spinner blurs into one: working normally, working slowly, and actually failed.
A good slow connection message appears only after a normal wait has already passed, so it does not cry wolf on every request. "Still working. Your connection looks slow right now" is honest and blames nothing. Pair it with a way out, usually a retry, and never let a slow state masquerade as a finished one. The worst version of this is the screen that silently gives up and shows an empty result, because the user reads no data as there is nothing here rather than we could not reach the server. That confusion is the bridge to the next section.
What MicroKopy generates around the wait
Here is the honest part, and it is the detail no competitor can give you. Everything in the three tables below was generated with MicroKopy's own prompt builders, the same ones behind the product's generator, then parsed and counted. Nobody wrote them by hand and none of them came from another app's screenshots.
One thing to be straight about. MicroKopy generates seven copy types, and a dedicated loading state is not one of them. There is no spinner-text preset. What the generator does cover is the copy that brackets a wait, the messages a user reads the instant the waiting ends, and those turn out to be where most of the writing actually lives. A wait resolves in one of three ways, and there is a copy type for each.
Each example carries its character count, spaces included, because length is the constraint that decides whether a line survives the slot it is written for. Read across the tone rows to see how far the wording moves while the fact underneath it holds still.
The wait that ends in nothing: empty states
The most confused pair in this whole area is the loading state and the empty state. A list that is still loading and a list that has nothing in it can look identical, and the fix is never to let the empty state render until the load has genuinely finished. Once it has, the empty state is doing the job the spinner was holding, so it is worth writing well. There is more on the design of these in empty state copy.
The three parts of each empty state below, a heading, a line of body, and a button, are separated by slashes here, and the count is for the generated string as a whole.
| Tone | Copy | Characters |
|---|---|---|
| Professional | No projects yet / Create your first project to start designing. Everything you build will show up here. / New Project | 113 |
| Professional | Your projects will live here / Start one now — you can invite teammates and add files later. / Create Project | 105 |
| Professional | Nothing here yet / Projects keep your designs, feedback, and files organized in one place. Create one to get started. / Start a Project | 131 |
| Friendly | No projects yet / This is where your projects will live. Create your first one to get started. / [Create project] | 109 |
| Friendly | Nothing here yet / Once you create a project, it'll show up on this page. / [New project] | 85 |
| Friendly | Let's build something / Your projects will appear here as soon as you create one. / [Start a project] | 97 |
| Playful | No projects yet / This is where your brilliant ideas will live. Create your first project to get started. / [Create project] | 120 |
| Playful | Nothing here... yet / Your project list is feeling a little empty. Let's fix that. / [Start a new project] | 102 |
| Playful | Blank canvas, big potential / Every great design starts with a single click. Make yours count. / [New project] | 106 |
| Minimal | No projects yet / Create your first project to start designing. / New Project | 73 |
| Minimal | Nothing here yet / Your projects will show up on this page. / Create Project | 72 |
| Minimal | Start your first project / Design, prototype, and share it all in one place. / Get Started | 86 |
Read down the column and the body line is where the work is. The heading just says the shelf is bare. The body is what turns an empty screen into a first step. Tone moves the wrapping a fair amount, from the flat minimal "Nothing here yet" to the playful "Blank canvas, big potential", and it costs characters to do it: the longest professional line runs to 131 while the tightest minimal one lands at 72 and still points the user at the one action that matters.
The wait that ends in a finished job: notifications
When a wait is long enough that you let the user leave, the spinner hands off to a notification. This is the far edge of a loading state. The export that took a minute is done, and the message is what brings the person back. If you write a lot of these, there is a dedicated guide to push notification copy. A push has two fields with two jobs and two separate ceilings, so each gets its own count below.
| Tone | Title | Title chars | Body | Body chars |
|---|---|---|---|---|
| Professional | [file_name] is ready | 20 | Your export finished processing. Tap to download [file_name] now. | 65 |
| Friendly | [file_name] is ready | 20 | Your export finished processing. Tap to download [file_name] now. | 65 |
| Playful | Export's done! 📦 | 17 | [file_name] is ready to download. Go on, show it off. | 53 |
| Minimal | Export complete | 15 | [file_name] is ready. Tap to download. | 38 |
The title identifies, the body gives the reason to tap. Notice that the operating system is the real editor here: a title over about thirty characters gets cut on a lock screen, which is why "Export complete" at 15 characters is safer than it looks, and the playful "Export's done!" leans on an emoji to carry tone without spending words. The body names the file and the single next action, download, and then stops.
The wait on an action you triggered: confirmations
The third kind of wait is the one you start on purpose. You hit delete on a project with forty files, the system takes a moment to do it, and then it confirms. The confirmation is the copy that closes that loop, and getting it right means naming what actually happened rather than a bland "Done". For the fuller treatment, graded by how reversible the action is, see confirmation dialog copy.
| Tone | Copy | Characters |
|---|---|---|
| Professional | Project deleted. All 40 files were removed along with it. | 57 |
| Professional | Done — the project and its 40 files are gone. Your dashboard is up to date. | 75 |
| Professional | Project and 40 files deleted. You can start a new project anytime. | 66 |
| Friendly | Project deleted. All 40 files are gone, along with the project itself. | 70 |
| Friendly | Done — your project and its 40 files have been deleted for good. | 64 |
| Friendly | Project removed. You can start a new one whenever you're ready. | 63 |
| Playful | Poof! Your project and all 40 files are gone for good. Ready to start something new? | 84 |
| Playful | Project deleted — all 40 files went with it. Clean slate, your move. | 68 |
| Playful | That's a wrap! Project and its 40 files have left the building. | 63 |
| Minimal | Project deleted. All 40 files are gone. | 39 |
| Minimal | Project and its 40 files are deleted. | 37 |
| Minimal | Deleted. Your workspace is back to normal. | 42 |
Across every tone the same instinct shows up: name the blast radius. "All 40 files" is doing the heavy lifting, not "deleted". The minimal "Project deleted. All 40 files are gone." gets the whole fact into 39 characters. And because these are reproduced exactly, you can see a habit worth knowing about: close to a third of the generated lines reach for a long dash to weld two clauses together, which is the punctuation this blog is written without. That is a real trait of the output, left in rather than tidied away, and it is part of the editing pass that any generated copy still needs before it ships.
Let the character counts guide the cut
The counts under every line are not decoration. Loading and status copy lives in some of the tightest slots in a product: a toast that spans the width of a phone, a notification title the operating system trims without asking, a button inside a progress dialog. Truncation is not a rare edge case here, it is the default outcome of writing to no limit at all. Decide the ceiling first, then write to it, and the generated options above become a shortlist you choose from rather than a draft you have to measure after the fact. This is the same discipline the pillar argues for across all seven types, and it is the one habit that separates copy that fits from copy that gets cut off mid-word.
A checklist for loading copy
- Match the words to the wait. Under a second, say nothing. Over ten, say what is happening and roughly how long.
- Keep skeleton screens quiet. If a word would read oddly after the content loads, leave it off during the load.
- Make progress honest. Name the real step or show the real count, and never fake a bar to ninety percent.
- Separate slow from failed. A slow connection message that offers a retry beats an empty screen that looks like a dead one.
- Write the end of the wait, not just the middle. The empty state, the notification, and the confirmation are where the user actually reads.
Where to start
Open your product and sit through its slowest screen on a throttled connection. Watch what it says while you wait, and more tellingly, what it says the moment the wait ends. Most of the time you will find a spinner with no words, an empty state that fires too early, and a confirmation that says "Done" and nothing else. Fix the end of the wait first, because that is the part the user reads. If you would rather start from generated options than a blank field, MicroKopy produces the empty states, notifications, and confirmations around a wait to a character ceiling you set, and you can see how that works on the features page. Good loading copy is not clever. It is a user who always knows whether to keep waiting, walk away, or try again.
Frequently asked questions
- What is loading state copy?
- Loading state copy is the small text a product shows while someone waits for something to finish: a spinner label, a progress message, a skeleton screen, or the message that appears the moment the wait ends. Its job is to tell the user whether to keep waiting, walk away, or try again.
- Should a skeleton screen have text?
- Usually not. A skeleton implies the structure of the page, so stamping the word Loading over it breaks the effect by announcing that the content is fake. When a region genuinely needs a word, use a quiet label tied to that region rather than a status for the whole screen.
- What should a progress message say?
- Name what is happening in terms the user recognises. "Compressing 12 of 40 files" tells someone more than "Please wait", and showing a real count or percentage reassures them that the work is moving. Never fake a progress bar, and only give a time estimate when it is roughly true.
- How do you write a slow connection message?
- Show it only after a normal wait has already passed, so it does not fire on every request, and blame nobody. "Still working. Your connection looks slow right now" is honest and pairs well with a retry. The key is to never let a slow state render as an empty result, which reads as failure.
- Does MicroKopy generate loading state copy?
- Not as a dedicated type. MicroKopy generates seven copy types, and a spinner-text preset is not one of them. What it does generate is the copy that brackets a wait: the empty state when a load returns nothing, the notification when a long job finishes, and the confirmation after an action completes. The examples in this post are those, generated with MicroKopy prompts and reproduced exactly.
- How long should loading and status messages be?
- Short enough to survive the slot, which is why every example here carries a character count. Notification titles get cut by the operating system around thirty characters, toasts span a phone width, and buttons inside a progress dialog are tighter still. Decide the ceiling first, then write to it.
We build the copy layer for product screens: tone presets, character ceilings and a review trail that travels with every string.
