The basic version of this task, upload a file, link to it, done, takes about ninety seconds in WordPress. Where it gets more interesting is everything that basic version doesn’t handle: knowing how many times a file has been downloaded, requiring an email address before someone gets the PDF, preventing a competitor from hotlinking directly to a paid resource, or serving a different file to logged-in members than to anonymous visitors. This covers the full range, starting with the native method and working through what each added layer of complexity actually buys you.
The native WordPress method: media library plus a link
WordPress doesn’t need a plugin to create a working download link, and for a simple, low-stakes file, this is genuinely the right amount of tooling, reaching for a plugin here is a common case of overbuilding a two-minute task.
- Go to Media » Add New in the dashboard and upload the file. WordPress accepts most common document, image, and audio formats out of the box; a handful of file types (like .zip or .exe) are blocked by default for security reasons and need a small code snippet or a plugin like WP Add Mime Types to allow if genuinely needed.
- Once uploaded, click the file in the media library and copy its URL from the “File URL” field in the attachment details panel.
- In the post or page editor, select the text or add an image/button you want to act as the download trigger, and add a link pointing to that copied URL.
- In the block editor’s link settings, there’s no dedicated “force download” toggle, by default, clicking the link opens the file in-browser if the browser knows how to render that file type (which is true for PDFs and images in essentially every modern browser). To force an actual download dialog instead of an in-browser preview, add the
downloadattribute to the link, which needs to be done through the Custom HTML block or by editing the link’s HTML directly, since the visual link UI doesn’t expose this attribute.
That download attribute distinction trips people up constantly. A plain link pointing to /wp-content/uploads/file.pdf with no extra attributes will open the PDF in a new browser tab on most setups, which might be exactly what you want for a resource meant to be read immediately, or might not be if you specifically want a file saved to the visitor’s device. Adding a download="filename.pdf" attribute to that same link changes the behavior to a direct download in supporting browsers, though the exact behavior still varies slightly by browser and by whether the file is same-origin or hosted elsewhere.
When the native method genuinely isn’t enough
The native approach has real limits, and recognizing which one applies to your situation determines which plugin (if any) is worth adding:
- No download count. There’s no built-in way to see how many times a file has been downloaded, if that number matters for reporting to a client, tracking content performance, or gating a resource behind a popularity threshold, you need a dedicated tool.
- No gating. The raw media library URL is public and guessable/crawlable the moment the post publishes, there’s no way to require an email opt-in, a login, or a purchase before the file is accessible, short of hiding the URL entirely (which isn’t real security, since URLs get indexed, shared, and cached).
- No expiration or access limits. A native media library link works forever, for anyone, with no way to set a download limit or an expiration date.
- Direct linking is trivial. Because the file sits at a predictable, public WordPress uploads URL, anyone who has ever seen the link can share or embed it directly, bypassing your page and any context or calls-to-action around the download.
Download Monitor: the standard choice for tracked, organized downloads
For sites managing more than a handful of downloadable files, documentation, whitepapers, plugin releases, media kits, Download Monitor is the most established free option, and it addresses most of the gaps above without requiring an e-commerce setup.
- Install and activate the Download Monitor plugin from the WordPress plugin repository.
- Go to the new “Downloads” menu item and select “Add New” to create a download entry, this is a separate content type from a regular post, purpose-built for managing files.
- Give the download a name, then in the “Download File” section, either upload a new file or select an existing one from the media library.
- In “Download Options,” configure anything relevant: a download limit per user, an expiration date, redirect behavior, or requiring the visitor to be logged in.
- Publish the download entry, then insert it into any post or page using the shortcode Download Monitor generates, typically
[download id="123"], or the plugin’s dedicated Gutenberg block if you’re on a recent WordPress version.
Once live, Download Monitor tracks every download event and surfaces basic analytics, total downloads, downloads over time, and which files are most popular, directly in the WordPress dashboard, without needing to wire up a separate analytics tool just to answer “is anyone actually downloading this.”
Gating downloads behind an email address
Lead-generation content (a whitepaper, a template, a checklist) usually needs an email capture step before the file releases, and this requires connecting a form tool to the download flow rather than linking directly to a file. The common pattern: build a form using a plugin like WPForms or Gravity Forms with an email field, then use that form’s “confirmation” or “redirect after submit” setting to either redirect the visitor to the actual file URL, or trigger an automated email containing the download link via the form’s email notification settings.
The second approach, emailing the link rather than redirecting immediately, has a real advantage: it verifies the email address is at least deliverable (a bounce reveals a fake or mistyped address) and it gives you a natural point to add the contact to an email list for follow-up, since most form plugins integrate directly with tools like Mailchimp or ActiveCampaign for that handoff. The tradeoff is friction, the visitor has to leave the page, check their inbox, and come back, and some percentage of interested people abandon that extra step. Which approach to use is a genuine tradeoff between lead quality and conversion volume, not a settled best practice either way.
Selling downloads: WooCommerce and Easy Digital Downloads
If the file is a paid product, an ebook, a set of templates, software, the download link itself becomes secondary to the checkout and access-control system around it. Two established options handle this differently:
- Easy Digital Downloads is purpose-built for selling digital files specifically, with download links generated automatically after purchase, expiring or limited-use download URLs baked in by default, and a customer account area where buyers can re-download past purchases without needing the original email. For a site selling only digital products, this focus generally means less setup overhead than adapting a broader e-commerce plugin to the same job.
- WooCommerce handles digital downloads as one product type among several (alongside physical and variable products), which makes it the better fit for a store selling a mix of digital and physical goods, or one already running WooCommerce for other reasons. Its digital download handling, expiring links, download limits per purchase, access tied to order status, covers roughly the same ground as Easy Digital Downloads’ core feature set, just as part of a larger, more general commerce toolkit.
Both platforms serve the actual file through a signed, temporary URL rather than the raw media library link, which closes the direct-linking and permanent-access gaps that plague the native WordPress method.
Restricting downloads to logged-in members
For a membership site, course platform, or client portal where downloads should only be available to specific logged-in users rather than the general public or anonymous form submitters, a membership plugin (MemberPress, Restrict Content Pro, or similar) typically handles this more cleanly than trying to bolt access control onto Download Monitor or a form plugin. These tools let you restrict entire pages, specific content blocks, or individual download links to users with a particular membership level, and they generally integrate with Download Monitor directly rather than requiring you to choose one or the other.
Preventing hotlinking and direct URL sharing
Even with a plugin managing the download flow, the underlying file often still sits at a static, guessable URL in the WordPress uploads directory unless the plugin specifically serves it through a redirect or a signed URL (Easy Digital Downloads and WooCommerce both do this by default; Download Monitor does this only if you enable “Xsendfile” or a similar direct-file-protection setting rather than linking to the raw uploads path). A few additional layers worth knowing about:
- .htaccess hotlink protection blocks other sites from embedding your file directly (a common problem for images and PDFs specifically), though this doesn’t stop someone from visiting the file URL directly in a browser, only from embedding it cross-site.
- Moving downloadable files outside the public uploads directory and serving them through a PHP script that checks permissions before streaming the file is the most robust approach, but it’s also the most technically involved, most premium download and membership plugins implement some version of this internally so you don’t have to build it yourself.
- Server-level access logs can reveal whether a file is being hit directly by bots or scrapers bypassing your intended download flow entirely, which is worth checking periodically for high-value paid content specifically.
Common problems and what actually causes them
A handful of issues account for most of the “my download link doesn’t work” reports:
- File opens in-browser instead of downloading. As covered above, this is expected default behavior for file types a browser can render (PDF, JPG, PNG, MP4) unless the
downloadattribute is explicitly set on the link, or the file is served through a plugin that forces a download header server-side. This isn’t a bug, it’s the browser doing what it’s designed to do absent an explicit instruction otherwise. - 404 error on the download link. Usually means the file was deleted or moved from the media library after the link was created, or the site migrated hosts/domains and the hardcoded URL in the post content still points to the old location. Search-and-replace tools (Better Search Replace is a common choice) can fix bulk broken links after a migration, but always back up the database before running one.
- Download works for admin but not for regular visitors. Almost always an access-restriction setting left too strict, a membership plugin rule scoped incorrectly, or a Download Monitor “logged in users only” toggle left on from testing. Always test the actual download flow in an incognito browser window logged out entirely, not just as an admin who bypasses most restrictions by default.
- File type blocked from uploading in the first place. WordPress restricts certain file extensions by default for security (executables, some archive formats depending on configuration). If a needed file type won’t upload, check the specific error message, it usually names the blocked extension directly, before assuming it’s a permissions or server issue.
Testing the actual download experience, not just the admin view
It’s easy to confirm a download link “works” by clicking it while logged into WordPress as an administrator, and easy to miss that the experience is completely different for an anonymous visitor. A short verification pass before considering any download link finished: open the page in a private/incognito browser window with no active session, click through the entire flow exactly as a first-time visitor would, and confirm the file actually downloads (or displays, if that’s the intent) rather than erroring, redirecting to a login screen unexpectedly, or silently failing. This is particularly important after adding any access-restriction plugin, since a misconfigured rule tends to fail in the direction of “blocks everyone” rather than failing visibly, and it’s easy not to notice because the admin testing it is usually exempt from the restriction being tested.
Mobile behavior is genuinely different, and worth checking separately
Download behavior on mobile browsers, particularly iOS Safari, frequently differs from desktop in ways that surprise people who only tested on a laptop. A PDF that neatly downloads to a folder on desktop Chrome might instead open directly in Safari’s built-in PDF viewer on an iPhone, with the “download” step requiring an extra tap on a share icon that isn’t obvious to someone unfamiliar with iOS conventions. For content where the download itself matters (a signed contract template, a coupon that needs to be saved for later use in-store), it’s worth testing the actual link on both a current iOS and a current Android device before assuming the desktop experience represents what most visitors will actually encounter, a large and growing share of overall web traffic is mobile, and file-download UX has historically lagged behind general mobile browsing polish.
A worked example: rolling out a gated resource
Picture a small consulting business publishing a downloadable pricing guide meant to double as a lead magnet. The build sequence in practice: first, the PDF gets uploaded to the media library and a WPForms form is built with name and email fields. The form’s confirmation setting is configured to redirect to a dedicated “thank you” page rather than showing the file inline, and that thank-you page itself contains the actual download link, this two-step structure means the download URL is one layer removed from being guessable directly from the original landing page, and it also gives a natural point to insert a calendar-booking widget or related content upsell. The form’s notification settings are wired to add each submitter’s email to the business’s mailing list automatically. Before launch, the whole flow gets tested twice: once in an incognito window to confirm the public path works end to end, and once on a phone to confirm the PDF actually opens or downloads cleanly on mobile Safari specifically, since that’s where a meaningful share of the traffic to a consulting site’s blog content tends to land from search and social referrals.
A quick decision guide
For a single, low-stakes file (a PDF menu, a one-off resource, an image) linked from a page: the native media library method is genuinely sufficient, and adding a plugin is unnecessary overhead. For multiple files needing download tracking or basic organization: Download Monitor. For lead generation gated behind an email address: a form plugin’s confirmation/notification flow. For selling digital products: Easy Digital Downloads if the store is exclusively digital, WooCommerce if it’s mixed with physical products or already in use. For member-only or course-gated content: a membership plugin layered on top of whichever download method above fits the content type.
The mistake to avoid is reaching for the heaviest tool by default. A site with three PDFs doesn’t need Easy Digital Downloads’ full checkout infrastructure any more than a site selling $500 courses should rely on a bare media library link with no access control, matching the tool to the actual stakes of the file being shared saves setup time on one end and prevents real security or revenue gaps on the other.