What is HtmlService?

Yes, that’s kinda on what Roblox page is made as well as DevForum.

There is a programming language called HTML which is used to build websites. This is what HtmlService is referencing.

That’s cool, I wish that it was still around now so that i can code in two different languages.

HTML and CSS are not programming languages. They are used for formatting web documents.

7 Likes

Let’s not stray off-topic, shall we?

It could have been possibly used for creating new window instances in Roblox 2007 (like clicking the Buy Robux button on the PromptPurchase gui).

I found some information on HtmlService.
image

11 Likes

I still wish it existed now because it would come useful for opening webpages in games and plugins.

2 Likes

Maybe you should add a solution now.

1 Like

Yeah, I know, right? We could make a working web browser with this using HttpService to fetch the HTML of the page, and use HtmlService to display it. But, there are some vulnerabilities, so I can understand why Roblox disabled it. For example, you could use a tracking pixel or a “web bug” in the page to potentially get a user’s IP address and their device info. However, this could be avoided by loading all external content on the page with a proxy. Plus, you usually can’t do much with an IP address. Typically, you can’t see a user’s personal information through an IP address, unless their WHOIS data is visible, which most ISPs hide. You could also potentially display inappropriate or suggestive images, but you can also do this right now by rendering each pixel as a frame inside of a GUI. So theoretically, if Roblox enabled HtmlService, it wouldn’t really pose that much of a threat to their users.

2 Likes

If you read a sentence in the image(down below), it basically was like a ScreenGui in a way, as users used HtmlService for shop windows and such. So to emulate it, you could HttpService and display the returned results as a GUI.

image

2 Likes

Yes, but it would be both hard and inefficient to convert HTML objects into Roblox GUI objects. For example, in Roblox, if you were to convert a simple 250x250 static image on a page to a viewable image by converting every pixel to a frame, you would need to render 62,500 objects! An example of this is CloneTrooper1019’s PNG Loader. Since it is rendering the image in 3-D with a heightmap, it needs to render a part for every pixel, since there isn’t a more efficient way of doing it. If you were to render it in 2-D, you would need a frame for every pixel. The HtmlService option would be way more efficient, as standard web browsers can render images very efficiently on the GPU, not by rendering every pixel as a frame like we have to do currently in Roblox. I guess you could potentially save rendering costs by using UIGradients, but that is hacky and still inefficient. Also, Roblox currently has no support for external fonts, it can’t render SVGs, et cetera. Having an HTML integration in GUIs, like an HtmlFrame object, would be nice.

2 Likes

I am now trying to make a HTML parser which can be used as a web browser.

3 Likes

If it helps you can try to build off of my parser that I abandoned a year and a half ago:

html.rbxl (26.7 KB)

3 Likes

Thank you. I will try to build of of it.

1 Like

Yes, thank you! I’ve been looking for one of these.

1 Like

(i know this topic is kind of old but i couldnt stop myself from showing that)

i found an old script from 2007 that used htmlservice so
i launched a 2007 roblox client and ran the following script

-- WARNING! For full functionality, do not edit this script!

local w = game:GetService("HtmlService"):NewWindow(470,530)

function getPlayer(humanoid) 
	local players = game.Players:children() 
		for i = 1, #players do 
			if players[i].Character.Humanoid == humanoid then return players[i] end 
		end 
	return nil 
end 

w:SetCallback(function(a) 
	print(a)

	if a == "help" then
		w:SetBody([==[
<table width="420" height="470" border="2" bordercolor="blue">
	<tr>
		<td width="490" bgcolor="#000000"><font color="#FFFF00">&nbsp;
			</font><div align="center">
				<p><font color="#FFFF00" size="6"><b>Chat: Help</b></font></p>
				<table width="410" height="0" border="2" bordercolor="blue">
					<tr>
						<td><p><font color="#FFFF00" size="4">Command:</font></p></td>
						<td><div align="center"><p><font color="#FFFF00">"help/"</font></p></div></td>
					</tr>
					<tr>
						<td><p><font color="#FFFF00" size="4">Function:</font></p></td>
						<td><div align="center"><p><font color="#FFFF00">Opens the Help window.</font></p></div></td>
					</tr>
				</table>
				<br>
				<input id="Button" type="button" width="20" value="Back" onclick="window.external.Call('back')" /><br />
			</div>
		</td>
	</tr>
</table>
		]==])
		w:Show()
	end

	if a == "vec" then
		w:SetBody([==[
<table width="420" height="470" border="2" bordercolor="blue">
	<tr>
		<td width="490" bgcolor="#000000"><font color="#FFFF00">&nbsp;
			</font><div align="center">
				<p><font color="#FFFF00" size="6"><b>Chat: Teleport</b></font></p>
				<table width="410" height="0" border="2" bordercolor="blue">
					<tr>
						<td><p><font color="#FFFF00" size="4">Command:</font></p></td>
						<td><div align="center"><p><font color="#FFFF00">"vec/Player/Vector3"</font></p></div></td>
					</tr>
					<tr>
						<td><p><font color="#FFFF00" size="4">Function:</font></p></td>
						<td><div align="center"><p><font color="#FFFF00">Moves Player's character to Vector3.</font></p></div></td>
					</tr>
				</table>
				<br>
				<input id="Button" type="button" width="20" value="Back" onclick="window.external.Call('back')" /><br />
			</div>
		</td>
	</tr>
</table>
		]==])
		w:Show()
	end

	if a == "admin" then
		w:SetBody([==[
<table width="420" height="470" border="2" bordercolor="blue">
	<tr>
		<td width="490" bgcolor="#000000"><font color="#FFFF00">&nbsp;
			</font><div align="center">
				<p><font color="#FFFF00" size="6"><b>Chat: Administration</b></font></p>
				<table width="410" height="0" border="2" bordercolor="blue">
					<tr>
						<td><p><font color="#FFFF00" size="4">Command:</font></p></td>
						<td><div align="center"><p><font color="#FFFF00">"admin/Player[/...]"</font></p></div></td>
					</tr>
					<tr>
						<td><p><font color="#FFFF00" size="4">Function:</font></p></td>
						<td><div align="center"><p><font color="#FFFF00">Adds Player to the permission list.<br>
							Extra arguments can be used for extra players.</font></p></div></td>
					</tr>
				</table>
				<br>
				<table width="410" height="0" border="2" bordercolor="blue">
					<tr>
						<td><p><font color="#FFFF00" size="4">Command:</font></p></td>
						<td><div align="center"><p><font color="#FFFF00">"unadmin/Player[/...]"</font></p></div></td>
					</tr>
					<tr>
						<td><p><font color="#FFFF00" size="4">Function:</font></p></td>
						<td><div align="center"><p><font color="#FFFF00">Removes Player from the permission list.<br>
							Extra arguments can be used for extra players.</font></p></div></td>
					</tr>
				</table>
				<br>
				<input id="Button" type="button" value="Back" onclick="window.external.Call('back')" /><br />
			</div>
		</td>
	</tr>
</table>
		]==])
		w:Show()
	end

	if a == "ban" then
		w:SetBody([==[
<table width="420" height="470" border="2" bordercolor="blue">
	<tr>
		<td width="490" bgcolor="#000000"><font color="#FFFF00">&nbsp;
			</font><div align="center">
				<p><font color="#FFFF00" size="6"><b>Chat: Ban</b></font></p>
				<table width="410" height="0" border="2" bordercolor="blue">
					<tr>
						<td><p><font color="#FFFF00" size="4">Command:</font></p></td>
						<td><div align="center"><div align="center"><p><font color="#FFFF00">"ban/Player[/...]"</font></p></div></td>
					</tr>
					<tr>
						<td><p><font color="#FFFF00" size="4">Function:</font></p></td>
						<td><div align="center"><div align="center"><p><font color="#FFFF00">Bans Player from the server.<br>
							Extra arguments can be used for extra players.</font></p></div></td>
					</tr>
				</table>
				<br>
				<input id="Button" type="button" width="20" value="Back" onclick="window.external.Call('back')" /><br />
			</div>
		</td>
	</tr>
</table>
		]==])
		w:Show()
	end

	if a == "boot" then
		w:SetBody([==[
<table width="420" height="470" border="2" bordercolor="blue">
	<tr>
		<td width="490" bgcolor="#000000"><font color="#FFFF00">&nbsp;
			</font><div align="center">
				<p><font color="#FFFF00" size="6"><b>Chat: Boot</b></font></p>
				<table width="410" height="0" border="2" bordercolor="blue">
					<tr>
						<td><p><font color="#FFFF00" size="4">Command:</font></p></td>
						<td><div align="center"><p><font color="#FFFF00">"boot/Player[/...]"</font></p></div></td>
					</tr>
					<tr>
						<td><p><font color="#FFFF00" size="4">Function:</font></p></td>
						<td><div align="center"><p><font color="#FFFF00">Removes Player from the server (player can come back).<br>
							Extra arguments can be used for extra players.</font></p></div></td>
					</tr>
				</table>
				<br>
				<input id="Button" type="button" width="20" value="Back" onclick="window.external.Call('back')" /><br />
			</div>
		</td>
	</tr>
</table>
		]==])
		w:Show()
	end

	if a == "kill" then
		w:SetBody([==[
<table width="420" height="470" border="2" bordercolor="blue">
	<tr>
		<td width="490" bgcolor="#000000"><font color="#FFFF00">&nbsp;
			</font><div align="center">
				<p><font color="#FFFF00" size="6"><b>Chat: Kill</b></font></p>
				<table width="410" height="0" border="2" bordercolor="blue">
					<tr>
						<td><p><font color="#FFFF00" size="4">Command:</font></p></td>
						<td><div align="center"><p><font color="#FFFF00">"kill/(1: all)(2: Player[/...])"</font></p></div></td>
					</tr>
					<tr>
						<td><p><font color="#FFFF00" size="4">Function(1):</font></p></td>
						<td><div align="center"><p><font color="#FFFF00">Kills all non-admin players.</font></p></div></td>
					</tr>
					<tr>
						<td><p><font color="#FFFF00" size="4">Function(2):</font></p></td>
						<td><div align="center"><p><font color="#FFFF00">Kills Player.<br>
							Extra arguments can be used for extra players.</font></p></div></td>
					</tr>
				</table>
				<br>
				<input id="Button" type="button" width="20" value="Back" onclick="window.external.Call('back')" /><br />
			</div>
		</td>
	</tr>
</table>
		]==])
		w:Show()
	end

	if a == "msg" then
		w:SetBody([==[
<table width="420" height="470" border="2" bordercolor="blue">
	<tr>
		<td width="490" bgcolor="#000000"><font color="#FFFF00">&nbsp;
			</font><div align="center">
				<p><font color="#FFFF00" size="6"><b>Chat: Message</b></font></p>
				<table width="410" height="0" border="2" bordercolor="blue">
					<tr>
						<td><p><font color="#FFFF00" size="4">Command:</font></p></td>
						<td><div align="center"><p><font color="#FFFF00">"m/Message[/Wait]"</font></p></div></td>
					</tr>
					<tr>
						<td><p><font color="#FFFF00" size="4">Function:</font></p></td>
						<td><div align="center"><p><font color="#FFFF00">Displays Message to all players.<br>
							An extra argument sets the duration of Message</font></p></div></td>
					</tr>
				</table>
				<br>
				<table width="410" height="0" border="2" bordercolor="blue">
					<tr>
						<td><p><font color="#FFFF00" size="4">Command:</font></p></td>
						<td><div align="center"><p><font color="#FFFF00">"h/Message"</font></p></div></td>
					</tr>
					<tr>
						<td><p><font color="#FFFF00" size="4">Function:</font></p></td>
						<td><div align="center"><p><font color="#FFFF00">Displays Message to all players in a hint</font></p></div></td>
					</tr>
				</table>
				<br>
				<table width="410" height="0" border="2" bordercolor="blue">
					<tr>
						<td><p><font color="#FFFF00" size="4">Command:</font></p></td>
						<td><div align="center"><p><font color="#FFFF00">"rh/"</font></p></div></td>
					</tr>
					<tr>
						<td><p><font color="#FFFF00" size="4">Function:</font></p></td>
						<td><div align="center"><p><font color="#FFFF00">Removes a hint if displayed</font></p></div></td>
					</tr>
				</table>
				<br>
				<table width="410" height="0" border="2" bordercolor="blue">
					<tr>
						<td><p><font color="#FFFF00" size="4">Command:</font></p></td>
						<td><div align="center"><p><font color="#FFFF00">"dm/"</font></p></div></td>
					</tr>
					<tr>
						<td><p><font color="#FFFF00" size="4">Function:</font></p></td>
						<td><div align="center"><p><font color="#FFFF00">Removes all messages and hints from all players and the workspace</font></p></div></td>
					</tr>
				</table>
				<br>
				<input id="Button" type="button" value="Back" onclick="window.external.Call('back')" /><br />
			</div>
		</td>
	</tr>
</table>
		]==])
		w:Show()
	end

	if a == "back" then
		w:SetBody([==[
<table width="420" height="470" border="2" bordercolor="blue">
	<tr>
		<td width="490" bgcolor="#000000"><font color="#FFFF00">&nbsp;
			</font><div align="center">
				<p><font color="#FFFF00" size="6"><b>Admin Help</b></font></p>

				<p><font color="#FFFF00">Click on one of the following buttons to learn their commands.</font></p>

				<input id="Button" type="button" style="width: 150px;" value="Help" onclick="window.external.Call('help')" /><br>
				<input id="Button" type="button" style="width: 150px;" value="Administration" onclick="window.external.Call('admin')" /><br>
				<input id="Button" type="button" style="width: 150px;" value="Vector3" onclick="window.external.Call('vec')" /><br>
				<input id="Button" type="button" style="width: 150px;" value="Ban" onclick="window.external.Call('ban')" /><br>
				<input id="Button" type="button" style="width: 150px;" value="Boot" onclick="window.external.Call('boot')" /><br>
				<input id="Button" type="button" style="width: 150px;" value="Kill" onclick="window.external.Call('kill')" /><br>
				<input id="Button" type="button" style="width: 150px;" value="Message" onclick="window.external.Call('msg')" /><br>
				<br>
				<input id="Button" type="button" value="Close" onclick="window.external.Call('close')" /><br>

				<p><font color="#FFFF00" size="1">All commands are in the following format: "[function]/[argument]/[argument]"</font></p>
			</div>
		</td>
	</tr>
</table>
		]==])
		w:Show()
	end

	if a == "close" then
		w:Close()
	end

end)

w.DocumentComplete:connect(function ()
	w:SetBody([==[
<table width="420" height="470" border="2" bordercolor="blue">
	<tr>
		<td width="490" bgcolor="#000000"><font color="#FFFF00">&nbsp;
			</font><div align="center">
				<p><font color="#FFFF00" size="6"><b>Admin Help</b></font></p>

				<p><font color="#FFFF00">Click on one of the following buttons to learn their commands.</font></p>

				<input id="Button" type="button" style="width: 150px;" value="Help" onclick="window.external.Call('help')" /><br>
				<input id="Button" type="button" style="width: 150px;" value="Administration" onclick="window.external.Call('admin')" /><br>
				<input id="Button" type="button" style="width: 150px;" value="Vector3" onclick="window.external.Call('vec')" /><br>
				<input id="Button" type="button" style="width: 150px;" value="Ban" onclick="window.external.Call('ban')" /><br>
				<input id="Button" type="button" style="width: 150px;" value="Boot" onclick="window.external.Call('boot')" /><br>
				<input id="Button" type="button" style="width: 150px;" value="Kill" onclick="window.external.Call('kill')" /><br>
				<input id="Button" type="button" style="width: 150px;" value="Message" onclick="window.external.Call('msg')" /><br>
				<br>
				<input id="Button" type="button" value="Close" onclick="window.external.Call('close')" /><br>

				<p><font color="#FFFF00" size="1">All commands are in the following format: "[function]/[argument]/[argument]"</font></p>
			</div>
		</td>
	</tr>
</table>
	]==])

	w:Show()
end)

w:Navigate()

and this happened

20 Likes

I suppose that after HTTPService was released they didn’t want people being able to display random (maybe questionable) webpages to Roblox players…

2 Likes

Yeah, but the thing is, you can technically do the same thing right now, just with GUI objects instead of HTML rendering, so you can do it but it’s just slow and inefficient. That’s why I wish Roblox would add HtmlService back, or at least a modern equivalent, because it would be an efficient way to display web pages.

2 Likes

Dude, that can be used to show obscene pictures. Roblox didn’t remove it?