WebView doesn't work

I run the following code on my IPhone, and log console.log returns null:

let webview = new WebView();

await webview.loadURL("https://google.com");

let dataGets = `
(function() {
var x = document.getElementsByClassName('o3j99');



let response = await webview.evaluateJavaScript(dataGets, true);


But if I run on the browser:

var x = document.getElementsByClassName('o3j99');

I get: <div class=​"o3j99 n1xJcf Ne6nSd">​…​</div>​flex<style data-iml=​"1639526495170"> .

So there you go, it’s not working at all.

I’m probably showing my ignorance here on more advanced JavaScript, but what is completion(x[0]);, and where is the x[0] element being passed back as a response value to be logged?

The completion function can be used to run async code with WebView.evaluateJavaScript( script, true) and any argument passed to it is returned in Scriptable.

You probably missed that it is in a string that is passed to evaluateJavaScript.

@jacku The element might not exist when Scriptable is executing your javascript code. You can try to add a delay with setTimeout before you query for the element. If this works out, then you can reduce the waiting time and retry until you find the element.

1 Like

I caught that it’s in the string, but I don’t recall ever coming across the completion function before. I can’t seem to find it through JavaScript documentation searches on Google, or in the Scriptable docs. My Google Fu has obviously deserted me this morning :sleeping:

Presumably you are only ever allowed one completion call per function scope and that is tied directly to the return then for this to work.

Where can I go to read more about it?


Yes, I’ve tried that but still the element isn’t found:

Yet on my chrome browser, as I’ve already stated, the element is found.

I’ve been at this the whole day yesterday, the scriptable app can’t find some elements for whatever reason. I’m in a rush for time too, so this is driving me crazy.

Have you tried to return the whole html tree and look for it or manually (or search for it)? maybe Google is using different classes on mobile…

It’s right there in the Scriptable docs. Ok, it’s a bit hidden:

When passing true to the useCallback parameter, evaluation will only complete after the globally available completion function is called. Any value passed to the function, will be carried by the promise returned by evaluateJavaScript.


1 Like

Yes, plenty a time. But it returns gibberish when I try to find “body” or “html”. On the Shortcurts app the “Run Javascript On” runs my scripts fine, and even running the javascript on mobile mode on my PC it runs fine too.

Here’s me returning the whole html tag.

Yes, it returns gibberish because Scriptable can only transfer primitive values (boolean, string, number) and it serializes any object into JSON. DOM Elements will also be serialized but that won’t give any meaningful result. You have to use .outerHTML on the element.

But that still doesn’t solve the issue that the element is not found. I’ve tried it myself with Scriptable and Shortcuts and both don’t find the element.

I can’t help you any further for now since I don’t know what you are trying to find.

It’s in German but it says that nothing was passed to the Quick Look action

For some ungodly reason the code:

const webview = new WebView();
await webview.loadURL("https://ordnet.dk/ddo/forside");

var getData = `
  function runit() {
    const ord = document.querySelector('.dagensord .match').innerText;
    completion (ord);


let response = await webview.evaluateJavaScript(getData, true);

Runs fine and returns the proper string:

But when I try to do it anywhere else, like google.com, it never returns anything. Incredible.

I’m almost positive, the issue is due to Scriptable not loading the elements right after the websites scripts load.

No, it’s because Google feels to have to be funny. I’ve now loaded google.com in mobile mode on my desktop and it returned a completely different HTML tree than in desktop mode. You will get different pages depending on the user agent string the browser is sending.

I run all commands on my PC in mobile mode. I assure the issue is elsewhere.

Is there some function that lets scriptable run all the website scripts?

Been going crazy over this for two days now.

There is absolutely no answer on google to this, I think the webview of scriptable is either broken or outdated.

Thanks, no wonder I wasn’t finding it. I’m used to seeing functions defined in documentation, not just referenced in passing as an implied definition :exploding_head:

No, the WebView is totally fine. Google is being funny. Try it with another page e.g. https://duckduckgo.com

let webview = new WebView();

await webview.loadURL("https://duckduckgo.com");

let dataGets = `
(function() {
var x = document.getElementsByClassName('content-wrap--home');



let response = await webview.evaluateJavaScript(dataGets, true);


logs this

2021-12-15 13:44:14: <div id="" class="content-wrap--home">
				<div id="content_homepage" class="content--home" style="visibility: visible;">
					<div class="cw--c">
								<div class="logo-wrap--home">
			<a id="logo_homepage_link" class="logo_homepage" href="/about">
				About DuckDuckGo
				<span class="logo_homepage__tt">Duck it!</span>

						<div class="search-wrap--home">
							<form id="search_form_homepage" class="search--home  js-search-form search--adv" name="x" method="GET" action="/">
    <input id="search_form_input_homepage" class="js-search-input search__input--adv" type="text" autocomplete="off" name="q" tabindex="1" value="" autocapitalize="off" autocorrect="off">
    <input id="search_button_homepage" class="search__button  js-search-button" type="submit" tabindex="2" value="S">
    <input id="search_form_input_clear" class="search__clear  empty  js-search-clear" type="button" tabindex="3" value="×">
    <div id="search_elements_hidden" class="search__hidden  js-search-hidden"><input type="hidden" class="js-search-hidden-field" name="t" value="h_"></div>
<div class="search__autocomplete"><div class="acp-wrap js-acp-wrap"></div><div class="acp-footer is-hidden js-acp-footer"><span class="acp-footer__instructions">Shortcuts zu anderen Sites, um außerhalb von DuckDuckGo zu suchen</span><span class="acp-footer__link"><a class="no-visited js-acp-footer-link" href="/bang">Mehr erfahren</a></span></div></div></form>


						<!-- de_DE Alle Einstellungen -->
    &lt;div class="tag-home"&gt;
        &lt;div class="tag-home__wrapper"&gt;
            &lt;div class="tag-home__item"&gt;
                Datenschutz – leicht gemacht&amp;period;
                &lt;span class="hide--screen-xs"&gt;&lt;a href="/about" class="tag-home__link"&gt;Mehr erfahren&lt;/a&gt;.&lt;/span&gt;
<div class="tag-home  tag-home--slide  no-js__hide  js-tag-home"><div class="tag-home__wrapper"><div class="tag-home__item">Datenschutz – leicht gemacht.<span class="hide--screen-xs"> <a class="tag-home__link js-tag-item-link" href="/spread">Hilf, DuckDuckGo zu verbreiten!</a></span></div></div></div>
<div id="error_homepage"></div>

					</div> <!-- cw -->
				</div> <!-- content_homepage //-->

When you run the commands in mobile mode on your desktop, what user agent string are you using? If you are using a Chrome or Firefox to check the HTML using the devtools, do you reload the page after switching to device mode? When I do that, I get a completely different HTML tree for google.com. This is not the case with duckduckgo.com.

1 Like

google.com was actually an example :slightly_frowning_face:, I’m using doing this to a different website that is also not working like Google is.

Any way I can fix this issue with Google.com?

You can try to use .loadRequest on the WebView and provide a desktop user agent string. Maybe then it will work.