• Skip to main content
  • Skip to header right navigation
  • Skip to site footer
Retro Game Coders

Retro Game Coders

Retro computer/console game + dev community

  • About
    • Retro Computer Collection
    • Contact
  • Blog
  • Retro Resources
    • Retro Gaming Timeline
    • Online Retro IDE
    • Retro Pixel Art Editor
    • Dungeon Loom Map Editor
    • 6502 Programmer’s Reference
    • Emulators
      • Acorn Electron
      • Amstrad CPC Emulator
      • Online BBC Micro Emulator
      • Commodore PET Emulator
      • Browser C64 Emulator
      • DOSBox/DOS PC emulator
      • Tandy CoCo/Dragon
    • Best Retro YouTube Channels
    • New Retro Books
    • Raspberry Pi Amiga Emulation
    • MiSTer FPGA Tutorial
    • BMC64 C64 Pi
  • Community

Home » Retro Game Coders Blog » Programming

Interacting with and Scraping the Web Using C64 & WiFi

Get your C64 onto the web and do interesting stuff! In this tutorial we look at how your Commodore 64 can get and use information via HTTP

Web browsing with the C64 is not really ideal, but that doesn’t mean you can’t interact over the web using your Commodore 64.

Huh? What?

Yes, that is right, we can hook up our C64 to the web and do interesting stuff!

If you haven’t already, check out how we get a C64 on the internet using a WiFi adapter.

Join Retro Game Coders Community
Join the Retro Game Coders Community

C64 WiFi and Vice Emulator

Once you have a WiFi adapter, you might find it handy to get your Vice emulator talking to it rather than code directly on your C64.

The way this works is Vice allows you to speak to your serial connection, you have to pick the appropriate serial port (in my case below you can see it is /dev/cu.usbserialXXX and select the Baud rate of 1200.

Having this setup means your code will be working with the actual WiFi adapter rather than emulating both the Commodore 64 and the WiFi device.

C64 Wifi Vice RS232 Settings
C64 Wifi Vice RS232 Settings

You can now follow the tutorials and edit the code right in your web browser with the Online Retro IDE

– No downloads, configuration, etc necessary, and it is free!

Interactive Serial Session

C64 interacting over Wifi
C64 interacting over Wifi

The first thing to try out is an interactive session, here you will type commands and hit enter, then see the results back. Just keep in mind the weird way the Commodore 64/PETSCII deals with upper and lower case.

This upper and lower case confusing will mean you will probably find it easier to set your baud rate to 1200 and set your wifi SSID and password using your computer serial (eg. the Arduino serial monitor, or command line terminal).

Essential C64 Wifi Commands

at? will list the available commands.

Arduino Serial Monitor hooked up to C64 WiFi
Arduino Serial Monitor hooked up to C64 WiFi

Enter atc1 to connect to Wifi, and ati to get the current WiFi configuration. AT&W will save your settings to the board’s flash memory so you don’t need to enter the WiFi details or baud rate again.

Once we are set up on WiFi, now we can move on to the Commodore 64 (or Vice), and BASIC. This code listing will act similar to typing in the serial monitor or terminal, but now it is all under control of the C64:

1 REM POKE 53272,23
2 PRINT CHR$(5): PRINT CHR$(147): PRINT CHR$(19);
3 OPEN2,2,4,CHR$(8)+CHR$(0):REM OPEN THE SERIAL FROM USER PORT
4 PRINT#2,"ATE0"
5 FOR I = 1 TO 10
6 GET#2,S$
7 PRINT S$;
8 NEXT
9 REM MAIN LOOP
10 GET K$:REM GET FROM C64 KEYBOARD
11 IF K$ = CHR$(13) THEN PRINT#2,CHR$(10)+CHR$(13);
12 IF K$<>"" AND K$ <> CHR$(13) THEN PRINT#2,K$;
13 GET#2,S$: REM GET BYTE FROM SERIAL
14 PRINT S$;:REM PRINT THESE BYTES
15 IF (PEEK(673)AND1)THEN GOTO 15:REM WAIT UNTIL ALL CHARS TRANSMITTED
16 GOTO 10
17 CLOSE 2:END

Once this is running, try getting a web page using atgethttp://example.com/ where example.com is your chosen website.

Getting Web Pages and Webhooks with C64

It won’t take long before you find websites where the URL paths are case sensitive and the weird case stylings of the C64 get annoying, so at that point you might want to store your URLs in BASIC programs and/or variables after converting them to the correct (inverted) case!

Eg. To select the third preset on my RGB LEDs I can use u$="atgethttp://192.168.0.103/WIN&a=64&pl=3"

See full code and WLED API tutorial here.

💬 Questions or comments? Head over to the community to discuss!

Sending Messages to Your Phone with Make

I set up a Webhook using the Make service:

Make Web Hook

The tool is amazing, with lots and lots of integrations, and now I have the C64Wifi firmware able to use SSL you can use the service, except the webhook URLs they give you are case sensitive (lower case), so I had to make my URL string Uppercase!

u$="atgethttps://hook.eu2.make.com/AD3..WJ1?message=c64+basic"

Now I can send messages to my phone from my C64!

Get the Current Time from TimeAPI

There is a nice, free Time API at, appropriately, TIMEAPI.IO with a lot of options. One of the most useful is to get the current time for a given time zone:

u$="atgetHTTPS://TIMEAPI.IO/API/TIMEZONE/ZONE?TIMEZONE=EUROPE/LONDON"

Using this we can get the current time, unfortunately C64 BASIC doesn’t have a way of searching within strings, and the serial connection between the modem and the Commodore 64 userport is unreliable (there is no flow control) so it could take a few attempts to actually get the correct time into our variables.

Set the C64 time with the internet
Set the C64 time with the internet

Here is the important part of the C64 BASIC code, you can get the full program here.

33 REM GET THE URL AND THEN
34 REM PARSE THE RESULT FROM TIMEAPI
35 PRINT#2,U$ + CHR$(10)+CHR$(13);:U$=""
36 PRINT ""
37 IF PEEK(673) AND 1 THEN PRINT ".";: GOTO 37: REM STILL TRANSMITTING
38 REM GET THE TIME
39 CC=0 : REM THE API WILL RETURN MORE CHARS THAT WE CAN USE
40 TS$ = "": NW$=""
41 GET#2,S$:IF S$<>"" AND CC < 255 THEN TS$ = TS$ + S$:CC=CC+1:GOTO 41
42 NW$=MID$(TS$,176,22): TS$=""
43 FOR C = 1 TO LEN(NW$)
44 C$ = MID$(NW$,C,1)
45 IF C$="T" THEN I=C
46 NEXT
47 H$=MID$(NW$,I+1,2)
48 M$=MID$(NW$,I+4,2)
49 S$=MID$(NW$,I+7,2)
50 PRINT ""
51 PRINT H$ + ":" + M$ + ":" + S$
52 PRINT ""
53 IF VAL(H$)<25 AND VAL(M$) < 60 AND VAL(S$)<60 THEN TIME$ = H$ + M$ + S$
54 GET#2,S$:IF S$<>"" THEN GOTO 54
55 FOR W=1 TO 2000: NEXT
56 RETURN

More Fun with APIs

As you can see, there are many, many things you can do once your computer is reading and writing to the web.

  • Get the weather in a location using HTTPS://V2.WTTR.IN/
Get the weather
Get the weather
  • Get a random number from random.org (in this case between 1 and 20) https://www.random.org/INTEGERS/?NUM=1&MIN=1&MAX=20&COL=1&BASE=10&FORMAT=PLAIN&RND=NEW
  • Get the definition of a dictionary word using DICTIONARYAPI.DEV (although it once loaded it seemed to make everything come back garbled on the C64, I think there were characters that upset the Commodore so I updated the C64 WiFi firmware to strip them – I probably still made a mistake somewhere)
rem weather
if i$="w" then print "w selected": u$="atgetHTTPS://V2.WTTR.IN/YORK,UK": gosub transmit

rem random
if i$="r" then print "r selected": u$="atgethttps://www.random.org/INTEGERS/?NUM=1&MIN=1&MAX=20&COL=1&BASE=10&FORMAT=PLAIN&RND=NEW": gosub transmit

rem dictionary
if i$="d" then print "d selected": u$="atgetHTTPS://API.DICTIONARYAPI.DEV/API/V2/ENTRIES/EN/NERD": gosub transmit

Here is the full C64 basic listing.

On the repo I also have it in more readable vs64 format.

1 POKE 53272,23
2 PRINT CHR$(5): PRINT CHR$(147): PRINT CHR$(19);: REM clear screen, white text
3 OPEN2,2,4,CHR$(8)+CHR$(0):REM OPEN THE SERIAL FROM USER PORT
4 PRINT "STARTING"
5 PRINT#2,"AT&K1":GOSUB 25
6 FOR I = 1 TO 5
7 GOSUB 33
8 NEXT
9 GOSUB 91
10 U$="": I$="": GET I$
11 IF I$="1" THEN PRINT "1 SELECTED": U$="ATGETHTTP://192.168.0.103/win&A=64&PL=1": GOSUB 25
12 IF I$="2" THEN PRINT "2 SELECTED": U$="ATGETHTTP://192.168.0.103/win&A=64&PL=2": GOSUB 25
13 IF I$="3" THEN PRINT "3 SELECTED": U$="ATGETHTTP://192.168.0.103/win&A=64&PL=3": GOSUB 25
14 IF I$="M" THEN PRINT "M SELECTED": U$="ATGETHTTPS://HOOK.EU2.MAKE.COM/ad3mie2ehs5uuhjo3n630yut9guhiwj1?MESSAGE=C64+BASIC": GOSUB 25
15 IF I$="T" THEN PRINT "T SELECTED": U$="ATGEThttps://timeapi.io/api/timezone/zone?timezone=europe/london": GOSUB 42
16 IF I$="W" THEN PRINT "W SELECTED": U$="ATGEThttps://v2.wttr.in/york,uk": GOSUB 67
17 IF I$="R" THEN PRINT "R SELECTED": U$="ATGETHTTPS://WWW.RANDOM.ORG/integers/?num=1&min=1&max=20&col=1&base=10&format=plain&rnd=new": GOSUB 25
18 IF I$="D" THEN PRINT "D SELECTED": U$="ATGEThttps://api.dictionaryapi.dev/api/v2/entries/en/nerd": GOSUB 25
19 IF I$ = "" THEN GOTO 10: REM LOOP BACK TO START OF THE MAIN LOOP AGAIN
20 FOR I = 1 TO 5
21 GOSUB 33
22 NEXT
23 GOTO 9
24 CLOSE 2: END
25 PRINT#2,U$ + CHR$(10)+CHR$(13);:U$=""
26 PRINT ""
27 IF PEEK(673) AND 1 THEN PRINT ".";: GOTO 27: REM STILL TRANSMITTING
28 FOR I = 1 TO 5
29 GOSUB 33
30 NEXT
31 RETURN
32 REM GET THE RESPONSE UNTIL NOTHING WAITING
33 S$="":GET#2,S$
34 IF S$="" THEN GOTO 38
35 IF S$=CHR$(13) OR S$=CHR$(10) THEN PRINT S$;:GOTO 33
36 IF S$<" " OR S$>"z" THEN GOTO 33
37 PRINT S$+"";:GOTO 33
38 FOR W=1 TO 400: NEXT
39 RETURN
40 REM GET THE URL AND THEN
41 REM PARSE THE RESULT FROM TIMEAPI
42 PRINT#2,U$ + CHR$(10)+CHR$(13);:U$=""
43 PRINT ""
44 IF PEEK(673) AND 1 THEN PRINT ".";: GOTO 44: REM STILL TRANSMITTING
45 REM GET THE TIME
46 CC=0 : REM THE API WILL RETURN MORE CHARS THAT WE CAN USE
47 TS$ = "": NW$=""
48 GET#2,S$:IF S$<>"" AND CC < 255 THEN TS$ = TS$ + S$:CC=CC+1:GOTO 48
49 NW$=MID$(TS$,176,22): TS$=""
50 FOR C = 1 TO LEN(NW$)
51 C$ = MID$(NW$,C,1)
52 IF C$="T" THEN I=C
53 NEXT
54 H$=MID$(NW$,I+1,2)
55 M$=MID$(NW$,I+4,2)
56 S$=MID$(NW$,I+7,2)
57 PRINT ""
58 PRINT H$ + ":" + M$ + ":" + S$
59 PRINT ""
60 IF VAL(H$)<25 AND VAL(M$) < 60 AND VAL(S$)<60 THEN TIME$ = H$ + M$ + S$
61 GET#2,S$:IF S$<>"" THEN GOTO 61
62 FOR W=1 TO 1000: NEXT
63 RETURN
64 GET#2,S$: IF S$<>"" GOTO 64
65 RETURN
66 REM WEATHER
67 REM GET THE URL AND THEN
68 REM PARSE THE RESULT FROM WEATHER URL
69 GOSUB 64
70 PRINT#2,U$ + CHR$(10)+CHR$(13);:U$=""
71 PRINT ""
72 IF PEEK(673) AND 1 THEN PRINT ".";: GOTO 72: REM STILL TRANSMITTING
73 FOR C=1 TO 1160: GET#2,S$: NEXT
74 REM WEATHER STRING LENGTH ~30
75 WL=50
76 GET#2,S$
77 IF S$ = CHR$(13) OR S$=CHR$(10) AND LEN(W$)
78 IF S$ >= " " AND S$ <= "z" AND LEN(W$)
79 IF LEN(W$)=WL THEN GOTO 83
80 IF S$<>"" GOTO 76
81 GOSUB 64
82 RETURN
83 PRINT CHR$(147)
84 PRINT "CURRENT WEATHER"
85 PRINT W$
86 W$=""
87 PRINT "": PRINT "PRESS A KEY"
88 GET K$: IF K$="" THEN GOTO 88
89 PRINT "PLEASE WAIT ..."
90 GOTO 64
91 PRINT CHR$(5): PRINT CHR$(147): PRINT CHR$(19);: REM clear screen, white text
92 PRINT "SELECT 1, 2 OR 3 FOR LED SEQUENCES"
93 PRINT "SELECT M TO SEND A MESSAGE TO IPHONE"
94 PRINT "SELECT T CURRENT TIME FROM THE INTERNET"
95 PRINT "SELECT W FOR WEATHER"
96 PRINT "SELECT R FOR RANDOM D20 ROLL"
97 PRINT "SELECT D FOR DICTIONARY"
98 RETURN

Get the full code on Github here!

Category: ProgrammingTag: basic programming, Commodore 64 (C64)
Previous Post:C64 BASIC Tutorial: Using String Manipulation to Write a Text Adventure
Next Post:C64 Text Adventure Game Programming TutorialC64 Text Adventure Game

Retro Game Coders

Retro computer/console game + dev programming community by Chris Garrett

  • Bluesky
  • Threads
  • Facebook
  • Instagram
  • YouTube
  • Mastodon

Maker Hacks ・ D6Combat・chrisg.com

© Copyright 2026 Chris Garrett

Privacy ﹒ Terms of Service

Return to top