You probably have to emulate some of the DOM, but you can interact directly with whatever obfuscated/packed scripts in a more lightweight and secure way than driving an entire browser.
Cue libv8-node+mini_racer from which PyMiniRacer was born. It is non-trivial but not as hard as one might think.
The most painful part is the libv8 build system and Google-centric tooling (depot tools!), which makes it an absolute PITA for libv8 consumers that are not Google/Chrome.
This is why the libv8 gem was atrocious to keep up to date and to build for several platforms, and why libv8-node was born, because the node build system and source distribution are actually sane (props to their relentless work on which we piggyback on)
Disclaimer: worked at Sqreen, now maintainer of libv8-node and collaborator of mini_racer
https://github.com/sqreen/PyMiniRacer
Over here we have a high interest in running JS code efficiently within multiple host languages. To that end we ported Ruby’s mini_racer to Python.
https://github.com/sqreen/PyMiniRacer
We also maintain a mini_racer fork and regularly try to backport performance improvements upstream.
We also support alternative platforms such as Alpine/musl and Solaris. One of our main pain points is that the whole libv8 tooling/build system is ever changing and terribly self-serving to Google, so as much as we want to improve support for additional platforms upstream, it’s a tall order to have our hacks to build for those cleaned up and merged there.
I introduce how I leveraged ctypes + Python manylinux wheels (PEP513 / PEP571) in order to allow loading V8 easily into Python, without requiring local compilation on install nor having us maintaining a huge test matrix:
$ pip install py-mini-racer
$ python
>>> from py_mini_racer import py_mini_racer
>>> ctx = py_mini_racer.MiniRacer()
>>> ctx.eval('1+1')
2
So this shared object could be used in any language allowing to interact with arbitrary shared objects (e.g. Ruby with fiddle).