Nativefier not working: what to check, in order
Most reports of Nativefier not working describe a symptom without saying where it appeared, and that is why the same question gets four unrelated answers. A failure during install, a build that finishes with the wrong name attached, a Mac that refuses to open the result, and a login page that rejects the window are four separate problems that share no fix. The order below separates them. Each stage has a single question that decides whether to keep going or stop and work there, and the checks are arranged so that the cheap ones come first.
Decide which stage broke before changing anything
There are four stages, and the boundaries between them are sharp.
The install stage ends when the command responds to --version. The build stage ends when a .app bundle appears in the output directory. The launch stage ends when a window appears on screen. The session stage covers everything after that, which is to say everything the site itself does.
Establishing the boundary takes one command. Ask the tool for its version. A clean answer means the install stage is finished and nothing there needs attention. Then look in the output directory for a bundle. If one exists, the build stage is finished too, regardless of whether the bundle carries the wrong name or the wrong icon, because those are build results rather than build failures.
The reason to be strict about this is that the advice for each stage is incompatible with the others. Reinstalling will not help a bundle that macOS refuses to open. Changing security settings will not help a build that never produced a bundle. Passing more flags will not help a login page that has already decided what kind of window it is talking to.
The --verbose flag exists for exactly this purpose and prints what the tool is deciding at each step, including the options it inferred rather than received. Running one verbose build before reading any advice usually removes half of the candidate explanations.
Stage one: the install does not finish, or finishes with warnings
The published requirements are Node 16.16.0 or later and npm 8.11.0 or later, which any current Mac exceeds. A clean install of version 52.0.0 on 12 September 2026, running Node 24.12.0 and npm 11.6.2, completed normally and pulled in 674 packages. A modern runtime is not the problem people expect it to be.
Two things in the output look like failures and are not.
The first is a deprecation notice pointing at the packaging library the project depends on. That library was renamed after this release was published, and the notice simply reports the rename. The build works.
The second is the security audit summary. That same install reported 30 advisories, 20 of them high and 2 critical, against the dependency tree. Neither the automatic fix nor an upgrade will clear them, because the versions are pinned by a lockfile inside the package and there is no later release. The advisories concern the tooling that runs during the build, not code that ships inside the finished app, but on a managed machine the number may still be the thing that stops the install, and no amount of retrying will change it.
A genuine install failure at this stage almost always names a permission or a path rather than a package. Installing globally writes outside the home directory, and a machine that restricts that will say so plainly. Installing into a project directory instead, and calling the binary from inside it, sidesteps the question entirely.
Stage two: the build finishes but produces the wrong thing
This is the most common report, and it is not a failure. The tool infers what it was not told, and the inference is literal.
The name comes from what the page says about itself. A build against a documentation site on 12 September 2026 produced an app named after the site's full marketing sentence, more than sixty characters long, which then became the folder name, the bundle name and the Dock label. Nothing went wrong. The page advertised that string and the tool believed it. Passing --name replaces the whole mechanism.
The icon follows the same rule with an extra dependency. Icons are converted with ImageMagick or GraphicsMagick, which are optional and not installed by default. Even with one of them present, a page that offers no icon the tool can find leaves the generic engine icon in place, which happened on both test builds. --icon pointing at a local image is the reliable route, and it is the only route if neither converter is installed.
Architecture is the third inference. The build targets the architecture of the Node process running it, so an Intel Mac produces an Intel bundle and an Apple silicon Mac produces an arm64 one. A bundle that runs slowly on a colleague's machine is usually this, and -a arm64 or -a x64 sets it explicitly.
One thing genuinely does fail at this stage: the engine download. The build fetches a full engine archive the first time a given version is needed, and the macOS arm64 archive for the default version is an 84 MB download. On a restricted network that download is what times out, and the symptom is a build that sits at the packaging step and then gives up.
Stage three: macOS refuses to open the bundle
The finished bundle is signed, but only with an ad hoc signature. On the test build, the signing tool reported the signature as ad hoc with no team identifier set, and the system assessment tool refused it. That is the expected result of building without a paid developer account, not a sign of a corrupted build.
Whether that matters depends entirely on how the bundle reached the Mac that is opening it. A bundle built on the same machine carries no quarantine attribute and opens by double click with no dialog at all. Send that same bundle to a colleague as a download or over AirDrop and quarantine applies, at which point the refusal appears.
Apple's documented route through is specific, and it is no longer the right click trick that older instructions describe:
After you've tried to open the app, follow these steps: Open System Settings. Click Privacy & Security, scroll down, and click the Open Anyway button to confirm your intent to open or install the app. Source: support.apple.com
The order matters. The button only appears after a launch attempt has been blocked, which is why instructions that start in System Settings appear to be wrong. The sequence is attempt, refusal, then settings.
A different message, saying the app is damaged rather than unverified, points at the transfer rather than the build. Archives that pass through some transfer paths lose the bundle's internal structure, and the fix is to move the original folder rather than a rebuilt archive of it.
Stage four: the window opens but the site will not cooperate
Once a window is on screen, the tool has done its job and everything remaining is a negotiation between the site and the engine.
Login refusals are the clearest case. Some services decline to authenticate inside an embedded browser as a matter of policy:
Google might stop sign-ins from browsers that: Don't support JavaScript or have JavaScript turned off. Have unsecure or unsupported extensions added. Are being controlled through software automation rather than a human. Are embedded in a different application. Source: support.google.com
There is a related detail that surprises people who go looking for a user agent flag. The app already presents itself as a plain Chrome browser by default, stripping the engine token and its own name out of the identifier before any request leaves. The flag that exists, --user-agent-honest, turns that disguise off rather than on. If a site is refusing the window, adding the disguise is not an available move, because it is already applied.
Protected video is the second case, and it is structural. Content protection needs a decryption module that a standard engine build does not carry. The --widevine flag exists and is documented as using an unofficial engine release provided by a third party, which is a different proposition from switching on a feature.
Links leaving the window is the third, and it is a setting rather than a fault. By default, addresses sharing the site's base domain stay inside and everything else opens in the normal browser. --internal-urls takes a regular expression that redraws that line, which is what a service spread across several domains needs.
Downloads are the fourth, and they behave differently from a browser because there is no download bar and no history to fall back on. The behaviour is configurable at build time through --file-download-options, which is worth setting deliberately for any site whose main purpose is producing files. A related flag, --clear-cache, stops the app preserving its cache between launches, and it is the one to reach for when a page renders from stale data that a browser reload would have replaced.
Stage five: a dialog appears months after everything was working
An app that behaved for a season and then started showing a warning on launch has not broken. Every built app records its own build date and checks it at startup. Past 90 days it shows a dialog titled "Old build detected" carrying the tool's own text:
This app was built a long time ago. Nativefier uses the Chrome browser (through Electron), and it is insecure to keep using an old version of it. Please upgrade Nativefier and rebuild this app. Source: github.com
There is a flag to suppress it, and its full name includes the phrase "yes i know it is insecure", which is the authors making a point rather than offering a setting. The intended answer is a rebuild, and there is a purpose built path for it: --upgrade takes the full path to the existing app and overwrites it while keeping the options the original was built with. That is a meaningfully different operation from building again from scratch and trying to remember which flags were used the first time.
The same dialog is a useful signal for a second reason. It marks the point at which the engine inside that particular app is at least three months further behind the browser on the same Mac, which is worth knowing before a site starts reporting that the browser is unsupported.
What to change first
Run one verbose build with --name and --icon set explicitly, since that removes the two most common false alarms before they happen. Then decide honestly whether a rebuild every 90 days is work worth doing per app, and if it is not, compare what a maintained route covers in the Guide and whether the service is already handled in the Supported services list. Kagemusha is built for the case where the answer to that question is no.
Frequently asked questions
Why does the built app open fine on one Mac and get blocked on another?
The bundle is ad hoc signed with no team identifier, so macOS cannot verify it. A bundle built on the machine that opens it carries no quarantine attribute and opens without a dialog. The same bundle transferred by download or AirDrop does carry one, which is when the refusal appears.
The install reports critical vulnerabilities. Can they be fixed?
Not from the install side. The dependency versions are pinned by a lockfile shipped inside the package, and version 52.0.0 from August 2023 is the last release, so there is nothing newer to upgrade to. The advisories concern build time tooling rather than code inside the finished app, but the count will keep growing.
A warning about an old build appeared after a few months. Is the app broken?
No. Every built app checks its own build date at launch and shows that dialog once it passes 90 days. The intended response is a rebuild, and the --upgrade flag takes the path to the existing app and overwrites it while keeping the options it was originally built with.
Google will not let anyone sign in inside the window. Is there a flag for that?
Not a useful one. Google's published policy is that sign ins may be blocked from browsers embedded in another application, and the app already presents a plain Chrome identifier by default. The only user agent flag available turns that disguise off rather than strengthening it, so signing in through the normal browser first is the practical route.