Why can't I click this button in the ChatGPT UI using standard JavaScript?

I want to script Safari to automate some actions in ChatGPT. To achieve that I need to click plus-button in the input field:

enter image description here

Usually when I try to do something like this I use JavaScript like

var button = document.evaluate("//div/div/div[2]/form/div[1]/div/div[2]/div/div[1]/div[1]/div/div/div/span[2]", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; button.click();

but for some reason this snippet doesn’t work - nothing happens - with the ChatGPT UI.

How do I click this button using JavaScript?

  1. I am aware of the ChatGPT API but it is not useful for my purpose.
  2. Safari has a do JavaScript method in its AppleScript dictionary that I use.

The reason your XPath-based JavaScript isn’t working in ChatGPT’s UI is likely due to React’s dynamic rendering and Shadow DOM, which makes elements harder to select using traditional methods like XPath. Also, ChatGPT uses event delegation and synthetic events, so a raw element.click() might not trigger expected behaviors.

Here’s how to robustly click the “+” (plus) button in Safari using JavaScript via AppleScript automation:
:white_check_mark: Step-by-step working script

Replace your XPath method with a querySelector based on class name or accessible label (when possible).

  1. Find the right element

Use the browser DevTools to inspect the “+” button and identify a stable class or aria-label.

For example, if the plus button has:

+

You can use:

document.querySelector(‘span[aria-label=“Add a file or image”]’).click();

  1. AppleScript to run it in Safari

Here’s how to run it via AppleScript in Safari:

tell application “Safari”
tell front document
do JavaScript “document.querySelector(‘span[aria-label="Add a file or image"]’).click();”
end tell
end tell

:exclamation:Troubleshooting tips

Wait for the page to fully load before executing the script.

If the button is in a Shadow DOM, you may need to traverse it manually (let me know, and I’ll help with that).

Class names in ChatGPT are obfuscated, so querySelector using them often breaks — use aria-label, role, or button text when available.

Why your button.click() doesn’t work:

  1. React uses synthetic events, not native ones:
  • element.click() triggers a native click, but React listens for synthetic events via internal event delegation. If you bypass React’s event system, nothing happens.
  1. DOM structure is dynamic:
  • The XPath you used is fragile. React frequently re-renders and reorganizes the DOM. What was div[2]/form/div[1]/div/... before may change any time—especially after UI updates.
  1. Element might not be ready:
  • If you run the script before the React component mounts (especially in Safari via AppleScript), the element may not exist yet.
  1. Shadow DOM / encapsulation:
  • Parts of the UI may be rendered within Shadow DOM-like boundaries or components that are difficult to traverse using basic JS.

:white_check_mark: How to click the button the right way:

First, identify the button more reliably, not via XPath but using accessibility labels, text content, or role attributes.

:white_check_mark: Example: Use aria-label

If the “+” button has something like:

<span aria-label="Add a file or image" role="button">+</span>

document.querySelector('span[aria-label="Add a file or image"]').click();
const el = document.querySelector('span[aria-label="Add a file or image"]');
if (el) {
  const event = new MouseEvent("click", {
    bubbles: true,
    cancelable: true,
    view: window
  });
  el.dispatchEvent(event);
}

Safari AppleScript Integration

Here’s how to run that script in Safari via AppleScript:

tell application "Safari"
    tell front document
        do JavaScript "
            const el = document.querySelector('span[aria-label=\"Add a file or image\"]');
            if (el) {
              const event = new MouseEvent('click', {
                bubbles: true,
                cancelable: true,
                view: window
              });
              el.dispatchEvent(event);
            }
        "
    end tell
end tell