A camera button can fail even when the browser's settings say that camera access is allowed. The page may be insecure, an embedding policy may block it, the operating system may deny the device, or the application may request a capability the browser does not support. A permission grant is only one part of the path.
Start by identifying the exact origin and operation. The origin includes scheme, hostname and port. A grant for one origin does not automatically apply to another. Then follow the request from API availability through browser policy, user permission and the actual device operation.
Inspect the origin that is making the request
The permissions audit queries states that the current browser exposes for this site's origin. It does not inspect grants held by other websites. Opening this tool and seeing a denied camera state therefore does not explain the permission held by a separate meeting application.
For an application bug, inspect its own site settings and run diagnostics in its document context. An embedded frame can have a different origin from the top-level page. The user may see the parent site's address while the feature request originates from a hosted widget underneath it.
Record redirects too. A service that moves from a bare domain to an application subdomain has changed origin. A development server on port 3000 is also different from one on port 8000. These differences often explain why a grant seems to disappear between otherwise similar pages.
Understand what the three states mean
A queryable permission can return granted, denied or prompt. Granted means the permission state currently permits access within the applicable rules. It does not guarantee that a device exists, is free or can satisfy the requested constraints. The actual operation can still fail.
Prompt means that an operation may require a user decision. Merely querying the state does not itself request a new grant. Denied means access is not permitted in the current state, but the state alone may not explain whether the cause is a user choice, an administrative rule or another applicable restriction.
Some permission names are not queryable in a particular browser. A rejected query is not equivalent to denied. The underlying feature may still have its own request flow. Keep unsupported query results separate from explicit states instead of converting every exception into a red permission badge.
| Observation | What you know | Useful next step |
|---|---|---|
| API missing | The interface is not exposed here | Check browser support and context requirements |
| Query returns prompt | No applicable grant is currently reported | Use the feature's normal user-triggered request |
| Query returns granted | Permission state allows the feature | Test device availability and constraints |
| Query throws | This query could not be completed | Check whether the permission name is supported |
| Operation rejects | The requested action failed | Preserve the error name and request context |
Check the secure context before asking again
Many powerful APIs require a secure context. A production page served over ordinary HTTP may not expose them even if the browser supports them generally. Local development origins can receive special treatment, so success on localhost does not prove that an HTTP staging hostname will behave the same way.
Inspect window.isSecureContext in the actual document. For embedded pages, the ancestor chain can matter. Repair the deployment and embedding conditions before repeatedly prompting the user to reset permissions. A permissions dialog cannot compensate for an API that is unavailable because its context requirements are unmet.
Also verify the certificate and final URL. A page that redirects unexpectedly or loads inside a different parent may have a context different from the one in the developer's notes. Include these details in the reproduction rather than reducing the report to a browser version and a screenshot.
Trace a camera widget through an iframe
Consider a support page at support.example embedding a video widget from call.example. The parent can restrict camera and microphone through Permissions Policy. The iframe's allow attribute can delegate features within the parent policy's limits. Neither mechanism supplies the user's permission or overrides an operating system block.
First test the widget as a top-level page with the same browser and account. If it works there but fails when embedded, investigate the parent response header and the actual iframe attributes. Inspect the rendered element, because a framework or hosting platform may alter attributes after the source template is written.
Next inspect browser console messages and the operation's error. Compare the permitted origins with the widget's final origin after redirects. A policy that names an old hostname can block the new deployment while looking reasonable in a configuration review.
Use a deliberate action to test the operation
Some capabilities require transient user activation or other interaction conditions. Run the request directly from an appropriate button or event handler, following the API's documentation. A delayed background call may behave differently from a request made during the user's action.
Request only what the workflow needs. If video capture fails, a smaller diagnostic request can help distinguish a missing device from an unsupported resolution constraint. Keep the original requested constraints in the report. A successful audio-only request does not prove that the combined audio-and-video request will work.
When the test obtains a media stream, stop its tracks after the diagnostic finishes. A forgotten stream can leave indicators active and interfere with later tests. The state of an earlier request can otherwise become an unrecorded variable in the next reproduction.
Offer recovery that matches the cause
If the user declined access, explain how to revisit the site's permission settings and offer a workflow that does not require the feature where possible. Avoid repeatedly launching the same request. Repetition does not fix a denial and makes it harder to understand what the application is asking for.
If policy blocks the feature, the application operator must fix the deployment. If the operating system denies access, direct the user to the relevant system setting. If no compatible device exists, changing a browser grant will not help. Error messages should distinguish these paths whenever the available evidence supports the distinction.
Keep a small diagnostic record: exact origin, top-level or embedded context, secure-context result, query result if supported, operation name, requested constraints and error name. Avoid storing device labels or persistent identifiers unless they are necessary for the issue. This record usually gives support enough information to route the problem.
Compare two development URLs precisely
Consider https://app.example:443 and https://app.example:8443. They share a hostname and both use HTTPS, but their effective ports differ, so they are different origins. A permission remembered for the first does not automatically describe the second. By contrast, explicitly writing the default HTTPS port and omitting it normally identifies the same effective origin.
Path changes such as /meeting and /settings do not create separate origins. If permission behaviour changes between those paths, inspect application code, frame structure and response policy rather than assuming the browser stores a grant for each path.
Put location.origin from the requesting document into your diagnostic record. It avoids ambiguity when a user copies a shortened address or when a reverse proxy exposes a different public port from the internal application server. Keep internal deployment details out of public reports unless they are needed.
Frequently asked questions
Can this audit list permissions for every site?
No. It queries what the page can observe for its own origin. Browser settings may provide a broader user-facing list, but a normal web page cannot use this API to enumerate all other sites' grants. Test the affected application in its own context or inspect its entry in the browser's settings.
Does querying permission open a dialog?
The Permissions API query reads state; it does not itself request access to a camera, microphone or location. The feature's own operation can trigger a permission flow when appropriate. Keep state inspection and access requests separate in your interface so that users understand which action actually uses a capability.
Why is camera granted but the call still fails?
The camera may be absent, busy, blocked by the operating system or unable to satisfy the application's constraints. An embedding policy can also restrict the operation. Record the rejection from the actual capture request and test a minimal supported configuration before changing the permission repeatedly.
Why does a private window behave differently?
Private contexts can use separate permission state, different extension availability and different persistence rules. They are useful comparison environments, but they are not identical copies of a normal profile with history removed. Record those differences and avoid attributing the result to a single cause without a controlled follow-up.
Can an iframe's allow attribute override a restrictive header?
No. Delegation operates within the restrictions that apply to the document hierarchy. A child cannot use its own configuration to grant a feature that an ancestor has forbidden. Review both the parent response header and the iframe attribute with the Permissions Policy analyzer, then confirm the browser's actual behaviour.
Should a denied state be cached permanently?
Permission state can change when users alter settings, navigate or use a different context. Handle changes and operation failures instead of assuming that the first query remains true forever. A cached state can improve interface responsiveness, but the requested operation remains the final check of whether access is currently possible.