{"id":364152,"date":"2026-09-11T20:13:18","date_gmt":"2026-09-11T20:13:18","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/scanupload\/"},"modified":"2026-09-11T20:12:57","modified_gmt":"2026-09-11T20:12:57","slug":"scanupload","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/scanupload\/","author":23548918,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.0.1","stable_tag":"1.0.1","tested":"7.1","requires":"6.0","requires_php":"7.4","requires_plugins":null,"header_name":"ScanUpload","header_author":"ScanUpload","header_description":"Let visitors scan a QR code to upload files from their phone directly into your WordPress site, powered by ScanUpload.","assets_banners_color":"5c708f","last_updated":"2026-09-11 20:12:57","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/app.scanupload.net\/integration","header_author_uri":"https:\/\/app.scanupload.net\/","rating":0,"author_block_rating":0,"active_installs":0,"downloads":42,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.1":{"tag":"1.0.1","author":"donaldanet1","date":"2026-09-11 20:12:57","revision":3692052}},"upgrade_notice":{"1.0.1":"<p>Compliance and code-quality release. No behaviour changes.<\/p>","1.0.0":"<p>Initial release.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3692051,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3692051,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3692051,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3692051,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.1"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3692051,"resolution":"1","location":"assets","locale":"","width":1280,"height":960},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3692051,"resolution":"2","location":"assets","locale":"","width":1280,"height":960},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3692051,"resolution":"3","location":"assets","locale":"","width":1280,"height":960},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3692051,"resolution":"4","location":"assets","locale":"","width":1280,"height":960},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3692051,"resolution":"5","location":"assets","locale":"","width":1280,"height":960},"screenshot-6.png":{"filename":"screenshot-6.png","revision":3692051,"resolution":"6","location":"assets","locale":"","width":1280,"height":960},"screenshot-7.png":{"filename":"screenshot-7.png","revision":3692051,"resolution":"7","location":"assets","locale":"","width":1280,"height":960}},"screenshots":{"1":"Settings, ScanUpload: add your Client ID and Client Secret.","2":"Choose where uploads land: the Media Library, attached to a page, or an uploads sub-folder.","3":"Advanced service endpoints, pre-filled with the ScanUpload defaults.","4":"ScanUpload active on the Plugins screen.","5":"Add <code>[scanupload]<\/code> to a page with the Shortcode block.","6":"The widget on a page, showing the live QR code for visitors to scan.","7":"Files received through the widget appear in the WordPress Media Library."}},"plugin_section":[],"plugin_tags":[5887,233,280303,1373,259],"plugin_category":[50],"plugin_contributors":[278534],"plugin_business_model":[],"class_list":["post-364152","plugin","type-plugin","status-publish","hentry","plugin_tags-file-upload","plugin_tags-media-library","plugin_tags-mobile-upload","plugin_tags-qr-code","plugin_tags-upload","plugin_category-media","plugin_contributors-donaldanet1","plugin_committers-donaldanet1"],"banners":{"banner":"https:\/\/ps.w.org\/scanupload\/assets\/banner-772x250.png?rev=3692051","banner_2x":"https:\/\/ps.w.org\/scanupload\/assets\/banner-1544x500.png?rev=3692051","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/scanupload\/assets\/icon-128x128.png?rev=3692051","icon_2x":"https:\/\/ps.w.org\/scanupload\/assets\/icon-256x256.png?rev=3692051","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/scanupload\/assets\/screenshot-1.png?rev=3692051","caption":"Settings, ScanUpload: add your Client ID and Client Secret."},{"src":"https:\/\/ps.w.org\/scanupload\/assets\/screenshot-2.png?rev=3692051","caption":"Choose where uploads land: the Media Library, attached to a page, or an uploads sub-folder."},{"src":"https:\/\/ps.w.org\/scanupload\/assets\/screenshot-3.png?rev=3692051","caption":"Advanced service endpoints, pre-filled with the ScanUpload defaults."},{"src":"https:\/\/ps.w.org\/scanupload\/assets\/screenshot-4.png?rev=3692051","caption":"ScanUpload active on the Plugins screen."},{"src":"https:\/\/ps.w.org\/scanupload\/assets\/screenshot-5.png?rev=3692051","caption":"Add <code>[scanupload]<\/code> to a page with the Shortcode block."},{"src":"https:\/\/ps.w.org\/scanupload\/assets\/screenshot-6.png?rev=3692051","caption":"The widget on a page, showing the live QR code for visitors to scan."},{"src":"https:\/\/ps.w.org\/scanupload\/assets\/screenshot-7.png?rev=3692051","caption":"Files received through the widget appear in the WordPress Media Library."}],"raw_content":"<!--section=description-->\n<p>ScanUpload adds a QR-code upload widget to any page with a shortcode. A visitor scans the QR code with their phone, uploads files, and those files are automatically imported into your WordPress site.<\/p>\n\n<p><strong>How it works<\/strong><\/p>\n\n<ol>\n<li>You add the <code>[scanupload]<\/code> shortcode to any page or post.<\/li>\n<li>The page renders a live QR code.<\/li>\n<li>A visitor scans it with their phone and uploads files using the ScanUpload mobile flow.<\/li>\n<li>Files arrive in your WordPress site automatically (Media Library or a sub-folder, your choice).<\/li>\n<\/ol>\n\n<p>The plugin is powered by the <a href=\"https:\/\/app.scanupload.net\/\">ScanUpload<\/a> service, which requires a free ScanUpload account, Client ID and Client Secret.<\/p>\n\n<p><strong>Features<\/strong><\/p>\n\n<ul>\n<li>Configurable Client ID and Client Secret, stored securely in the WordPress options table.<\/li>\n<li>Choose where uploads land: Media Library (unattached), Media Library attached to a post\/page, or a dedicated uploads sub-folder.<\/li>\n<li>Live file preview while the visitor uploads.<\/li>\n<li>Fully automatic import - no button clicks required.<\/li>\n<li>Works on any theme via the <code>[scanupload]<\/code> shortcode.<\/li>\n<\/ul>\n\n<h4>Getting started<\/h4>\n\n<ol>\n<li>Create a free account at <a href=\"https:\/\/app.scanupload.net\/\">app.scanupload.net<\/a> and copy your <strong>Client ID<\/strong> and <strong>Client Secret<\/strong> from <strong>Dashboard \u2192 Settings \u2192 Client Credentials<\/strong>.<\/li>\n<li>In WordPress, open <strong>Settings \u2192 ScanUpload<\/strong>, paste both values and click <strong>Save Settings<\/strong>.<\/li>\n<li>In the ScanUpload Dashboard, add your site address to <strong>Allowed Origins<\/strong> (for example <code>https:\/\/example.com<\/code>). While developing on <code>localhost<\/code>, enable <strong>Test Mode<\/strong> instead.<\/li>\n<li>Add the <code>[scanupload]<\/code> shortcode to the page where you want the widget (see below).<\/li>\n<\/ol>\n\n<p>That is the whole configuration. Until credentials are saved, the widget shows a friendly \"ScanUpload is not configured\" message instead of a QR code.<\/p>\n\n<h4>Putting the widget on a page<\/h4>\n\n<p><strong>Block Editor (nothing extra to install):<\/strong> edit the page, click <strong>+<\/strong>, search for <strong>Shortcode<\/strong>, add the block and paste <code>[scanupload]<\/code> into it.<\/p>\n\n<p><strong>Elementor:<\/strong> drag the <strong>Shortcode<\/strong> widget into the page and paste <code>[scanupload]<\/code> into its Shortcode field.<\/p>\n\n<p><strong>Any other theme or builder that renders shortcodes:<\/strong> paste <code>[scanupload]<\/code> where the widget should appear.<\/p>\n\n<p>A visitor then points their phone camera at the code, chooses the files they want to send, and the files arrive on your site automatically. The widget lists each file as it arrives, so the visitor can see the upload working.<\/p>\n\n<h4>Where do the files go?<\/h4>\n\n<ul>\n<li><strong>Media Library, unattached<\/strong> (<code>import_mode=\"media\"<\/code>, the default) - files appear under <strong>Media \u2192 Library<\/strong>.<\/li>\n<li><strong>Media Library, attached to a post or page<\/strong> (<code>import_mode=\"media_attach\"<\/code>) - files appear in the library, attached to the post or page you choose.<\/li>\n<li><strong>A sub-folder of the uploads directory<\/strong> (<code>import_mode=\"folder\"<\/code>) - files are saved under <code>wp-content\/uploads\/&lt;sub-folder&gt;\/<\/code> and are not added to the Media Library.<\/li>\n<\/ul>\n\n<p>In <code>folder<\/code> mode the plugin also writes <code>.htaccess<\/code>, <code>index.html<\/code> and <code>web.config<\/code> guard files into that folder so uploaded files cannot be executed.<\/p>\n\n<h4>Shortcode<\/h4>\n\n<pre><code>[scanupload]\n<\/code><\/pre>\n\n<p>Optional attributes:<\/p>\n\n<ul>\n<li><code>header<\/code> - Header text shown above the QR code. Default: \"Upload files from your phone\".<\/li>\n<li><code>show_header<\/code> - <code>1<\/code> or <code>0<\/code>. Default <code>1<\/code>.<\/li>\n<li><code>size<\/code> - <code>small<\/code>, <code>medium<\/code>, <code>large<\/code> or <code>xlarge<\/code>. Default <code>large<\/code>.<\/li>\n<li><code>file_preview_mode<\/code> - <code>list<\/code> or <code>grid<\/code>. Default <code>list<\/code>.<\/li>\n<li><code>import_mode<\/code> - <code>media<\/code>, <code>media_attach<\/code> or <code>folder<\/code>. Overrides the site-wide setting for this widget.<\/li>\n<li><code>attach_to<\/code> - Post ID to attach imported media to when <code>import_mode=\"media_attach\"<\/code>. Use <code>attach_to=\"current\"<\/code> to attach to the post currently being viewed.<\/li>\n<li><code>class<\/code> - Extra CSS class for the widget container.<\/li>\n<\/ul>\n\n<p>Example:<\/p>\n\n<pre><code>[scanupload header=\"Scan to send us files\" size=\"large\" import_mode=\"media_attach\" attach_to=\"42\"]\n<\/code><\/pre>\n\n<p>When a logged-in visitor uploads files, the imported attachments are attributed\nto that user. Anonymous visitors upload unattributed (author 0).<\/p>\n\n<p>Media is only attached to a post the uploader is allowed to edit; otherwise it\nis imported unattached. Use the <code>scanupload_allow_attach_to_post<\/code> filter to\nallow guest submissions to a fixed public post.<\/p>\n\n<h4>Developer Hooks<\/h4>\n\n<ul>\n<li><code>scanupload_import_author_id<\/code> - author ID assigned to imported attachments (default: the current user, <code>0<\/code> for anonymous visitors).<\/li>\n<li><code>scanupload_allow_attach_to_post<\/code> - whether imported media may be attached to a post (default: only when the uploader can edit it). Use it to allow guest submissions to a fixed public post.<\/li>\n<li><code>scanupload_import_rate_limit<\/code> - maximum import requests per rate-limit window (default <code>10<\/code>).<\/li>\n<li><code>scanupload_import_rate_window<\/code> - rate-limit window in seconds (default <code>600<\/code>, i.e. 10 minutes).<\/li>\n<li><code>scanupload_import_client_ip<\/code> - client IP used for rate limiting (default: the direct peer address). Useful behind a trusted reverse proxy.<\/li>\n<\/ul>\n\n<h4>External services and data<\/h4>\n\n<p>This plugin is a bridge to the <a href=\"https:\/\/app.scanupload.net\/\">ScanUpload<\/a> service and only connects to it when you configure it and a visitor uses the widget:<\/p>\n\n<ul>\n<li>The visitor's browser creates a scan upload session with ScanUpload (<code>https:\/\/hub.scanupload.net<\/code>) when a <code>[scanupload]<\/code> widget is shown. The browser sends only the configured Client ID and your site's origin.<\/li>\n<li>Your server requests an access token from the ScanUpload identity service (<code>https:\/\/identity.scanupload.net<\/code>) using the Client ID and Client Secret you entered.<\/li>\n<li>Your server downloads the uploaded files for a session and imports them into your own WordPress site.<\/li>\n<\/ul>\n\n<p>No tracking or analytics data is collected or sent by this plugin. Uploaded files are transmitted to and from the ScanUpload service solely to operate the upload feature, and are then stored on your site. No data is shared with any third party. See the <a href=\"https:\/\/app.scanupload.net\/terms-conditions\">ScanUpload Terms and Conditions<\/a> for how ScanUpload handles the files it processes.<\/p>\n\n<p>By installing, configuring and using the plugin you consent to the connections described above.<\/p>\n\n<h3>Credits<\/h3>\n\n<p>This plugin bundles the following open-source libraries. Both are included as\nreadable, unminified source so the shipped code can be reviewed as-is:<\/p>\n\n<ul>\n<li><a href=\"https:\/\/github.com\/dotnet\/aspnetcore\">@microsoft\/signalr<\/a> - MIT License. Used for the live file preview.<\/li>\n<li><a href=\"https:\/\/github.com\/kazuhikoarase\/qrcode-generator\">qrcode-generator<\/a> - MIT License. Used to render the QR code.<\/li>\n<\/ul>\n\n<p>Both licences are GPL-compatible. The plugin's own code is licensed under\nGPL-2.0-or-later; see <code>license.txt<\/code>.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>In your WordPress admin, go to <strong>Plugins \u2192 Add New<\/strong>, search for <strong>ScanUpload<\/strong>, then click <strong>Install Now<\/strong>. Alternatively, upload the plugin ZIP under <strong>Plugins \u2192 Add New \u2192 Upload Plugin<\/strong>.<\/li>\n<li>Click <strong>Activate<\/strong>.<\/li>\n<li>Continue with <strong>Getting started<\/strong> above: save your Client ID and Client Secret, allow your site origin, then add the <code>[scanupload]<\/code> shortcode to a page.<\/li>\n<\/ol>\n\n<p><strong>Requirements:<\/strong> WordPress 6.0+, PHP 7.4+, a free ScanUpload account, and HTTPS. The widget opens a secure WebSocket to the ScanUpload hub, so an HTTP page is blocked by the browser's mixed-content protection.<\/p>\n\n<!--section=faq-->\n<dl>\n<dt id=\"do%20i%20need%20a%20scanupload%20account%3F\"><h3>Do I need a ScanUpload account?<\/h3><\/dt>\n<dd><p>Yes. Create a free account at <a href=\"https:\/\/app.scanupload.net\/\">app.scanupload.net<\/a>, then generate a Client ID and Client Secret from the Dashboard.<\/p><\/dd>\n<dt id=\"is%20my%20client%20secret%20exposed%20to%20visitors%3F\"><h3>Is my Client Secret exposed to visitors?<\/h3><\/dt>\n<dd><p>No. The Client Secret is used only on your server to download uploaded files. It is never printed in the page source.<\/p><\/dd>\n<dt id=\"why%20do%20i%20get%20an%20%22origin%20not%20allowed%22%20error%3F\"><h3>Why do I get an \"origin not allowed\" error?<\/h3><\/dt>\n<dd><p>ScanUpload validates the browser origin that creates a session. Add your exact site origin (for example <code>https:\/\/example.com<\/code>) to <strong>Allowed Origins<\/strong> in the ScanUpload Dashboard. Origins are scheme, host and port specific.<\/p><\/dd>\n<dt id=\"can%20i%20test%20on%20localhost%3F\"><h3>Can I test on localhost?<\/h3><\/dt>\n<dd><p>Yes. Enable <strong>Test Mode<\/strong> in the ScanUpload Dashboard to bypass origin validation for local development, and disable it before going live.<\/p><\/dd>\n<dt id=\"where%20are%20the%20files%20stored%3F\"><h3>Where are the files stored?<\/h3><\/dt>\n<dd><p>By default they are imported into the WordPress Media Library. You can change this under <strong>Settings \u2192 ScanUpload<\/strong> to attach them to a post\/page or save them in a sub-folder of the uploads directory.<\/p><\/dd>\n<dt id=\"does%20my%20site%20need%20to%20be%20https%3F\"><h3>Does my site need to be HTTPS?<\/h3><\/dt>\n<dd><p>Yes. The widget connects to the ScanUpload hub over a secure WebSocket (<code>wss:\/\/<\/code>), so your site must be served over HTTPS. An HTTP page is blocked by the browser's mixed-content protection.<\/p><\/dd>\n<dt id=\"what%20if%20my%20site%20has%20a%20content%20security%20policy%20%28csp%29%3F\"><h3>What if my site has a Content Security Policy (CSP)?<\/h3><\/dt>\n<dd><p>Allow the hub for both protocols in your <code>connect-src<\/code> directive:<\/p>\n\n<pre><code>connect-src 'self' https:\/\/hub.scanupload.net wss:\/\/hub.scanupload.net;\n\nhttps:\/\/ permits the session request and `wss:\/\/` permits the live SignalR updates. CSP does not infer one from the other.\n<\/code><\/pre><\/dd>\n<dt id=\"where%20can%20i%20get%20help%3F\"><h3>Where can I get help?<\/h3><\/dt>\n<dd><p>Email <a href=\"mailto:support@scanupload.net\">support@scanupload.net<\/a> or see the <a href=\"https:\/\/app.scanupload.net\/integration\">ScanUpload integration guide<\/a>.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.1<\/h4>\n\n<ul>\n<li>Replaced direct filesystem calls with WordPress APIs (<code>wp_delete_file()<\/code> and <code>WP_Filesystem<\/code>), removed the redundant <code>load_plugin_textdomain()<\/code> call, and added translator comments for placeholder strings. No behaviour changes.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release: settings page, <code>[scanupload]<\/code> shortcode, live QR widget, SignalR file preview, and automatic import into the Media Library or uploads sub-folder.<\/li>\n<\/ul>","raw_excerpt":"Let visitors scan a QR code to upload files from their phone straight into your WordPress Media Library, powered by ScanUpload.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/364152","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=364152"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/donaldanet1"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=364152"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=364152"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=364152"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=364152"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=364152"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=364152"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}