diff --git a/gajim/common/config.py b/gajim/common/config.py
index 47299b3fc6e90dc2c2a27f82311b593e19a576de..d120d90eacf6089c391f2c064cc95481dd82ffef 100644
--- a/gajim/common/config.py
+++ b/gajim/common/config.py
@@ -250,6 +250,8 @@ class Config:
         'groupchat_roster_width': [opt_int, 210, _('Width of group chat roster in pixel')],
         'dev_force_bookmark_2': [opt_bool, False, _('Force Bookmark 2 usage')],
         'show_help_start_chat': [opt_bool, True, _('Shows an info bar with helpful hints in the Start / Join Chat dialog')],
+        'check_for_update': [opt_bool, True, _('Check for Gajim updates periodically')],
+        'last_update_check': [opt_str, '', _('Date of the last update check')],
     }, {})  # type: Tuple[Dict[str, List[Any]], Dict[Any, Any]]
 
     __options_per_key = {
diff --git a/gajim/data/gui/preferences_window.ui b/gajim/data/gui/preferences_window.ui
index 3cc3a9bd68f840d687cc1e1da9e39bab2b21feda..94bd9a01bbc4fb6895b152dc14fda4646600db9e 100644
--- a/gajim/data/gui/preferences_window.ui
+++ b/gajim/data/gui/preferences_window.ui
@@ -2771,6 +2771,26 @@ to discover one from the server. (Example: stun.iptel.org)</property>
                         <property name="position">3</property>
                       </packing>
                     </child>
+                    <child>
+                      <object class="GtkCheckButton" id="update_check">
+                        <property name="label" translatable="yes">_Check for Gajim updates periodically</property>
+                        <property name="visible">True</property>
+                        <property name="sensitive">False</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="no_show_all">True</property>
+                        <property name="tooltip_text" translatable="yes">Enables a weekly update check (Windows only)</property>
+                        <property name="halign">start</property>
+                        <property name="use_underline">True</property>
+                        <property name="draw_indicator">True</property>
+                        <signal name="toggled" handler="_on_update_check_toggled" swapped="no"/>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">3</property>
+                      </packing>
+                    </child>
                     <child>
                       <object class="GtkButton" id="reset_help">
                         <property name="label" translatable="yes">_Reset Hints</property>
diff --git a/gajim/gtk/preferences.py b/gajim/gtk/preferences.py
index 99587c34d1616264be00915e7ef20d977a84e176..1f0e00359668f18e3c1987418f32c06f63ef2931 100644
--- a/gajim/gtk/preferences.py
+++ b/gajim/gtk/preferences.py
@@ -14,6 +14,7 @@
 
 import logging
 import os
+import sys
 
 from gi.repository import GLib
 from gi.repository import Gtk
@@ -429,6 +430,11 @@ def create_av_combobox(opt_name, device_dict, config_name=None,
         self._ui.enable_logging.set_active(app.get_debug_mode())
         self._ui.enable_logging.show()
 
+        if sys.platform in ('win32', 'darwin'):
+            st = app.config.get('check_for_update')
+            self._ui.update_check.set_active(st)
+            self._ui.update_check.show()
+
         self._ui.connect_signals(self)
         self.connect('key-press-event', self._on_key_press)
 
@@ -1066,6 +1072,9 @@ def on_enable_logging_toggled(self, widget):
     def _on_debug_folder_clicked(self, _widget):
         open_file(configpaths.get('DEBUG'))
 
+    def _on_update_check_toggled(self, widget):
+        self.on_checkbutton_toggled(widget, 'check_for_update')
+
     def _on_reset_help_clicked(self, widget):
         widget.set_sensitive(False)
         helping_hints = [
diff --git a/gajim/gui_interface.py b/gajim/gui_interface.py
index c0d112d725e77306ed18f2581c76a7193f2bec56..08a81a5d86c6ccf52bd00089fa571b2512db53f2 100644
--- a/gajim/gui_interface.py
+++ b/gajim/gui_interface.py
@@ -35,14 +35,18 @@
 import sys
 import re
 import time
+import json
 import logging
 from functools import partial
 from threading import Thread
+from datetime import datetime
 from importlib.util import find_spec
+from packaging.version import Version as V
 
 from gi.repository import Gtk
 from gi.repository import GLib
 from gi.repository import Gio
+from gi.repository import Soup
 from nbxmpp import idlequeue
 from nbxmpp import Hashes2
 
@@ -91,6 +95,7 @@
 from gajim.gtk.dialogs import WarningDialog
 from gajim.gtk.dialogs import InformationDialog
 from gajim.gtk.dialogs import NewConfirmationDialog
+from gajim.gtk.dialogs import NewConfirmationCheckDialog
 from gajim.gtk.dialogs import InputDialog
 from gajim.gtk.dialogs import PassphraseDialog
 from gajim.gtk.dialogs import InvitationReceivedDialog
@@ -1839,6 +1844,81 @@ def create_zeroconf_default_config(self):
         app.config.set_per('accounts', app.ZEROCONF_ACC_NAME,
                 'active', False)
 
+    def check_for_updates(self):
+        if not app.config.get('check_for_update'):
+            return
+
+        now = datetime.now()
+        last_check = app.config.get('last_update_check')
+        if not last_check:
+            def _on_cancel():
+                app.config.set('check_for_update', False)
+
+            def _on_check():
+                self._get_latest_release()
+
+            NewConfirmationDialog(
+                _('Update Check'),
+                _('Gajim Update Check'),
+                _('Search for Gajim updates periodically?'),
+                [DialogButton.make('Cancel',
+                                   text=_('_No'),
+                                   callback=_on_cancel),
+                 DialogButton.make('Accept',
+                                   text=_('_Search Periodically'),
+                                   callback=_on_check)]).show()
+            return
+
+        last_check_time = datetime.strptime(last_check, '%Y-%m-%d %H:%M')
+        if (now - last_check_time).days < 7:
+            return
+
+        self._get_latest_release()
+
+    def _get_latest_release(self):
+        log.info('Checking for Gajim updates')
+        session = Soup.Session()
+        session.props.user_agent = 'Gajim %s' % app.version
+        message = Soup.Message.new('GET', 'https://gajim.org/current-version.json')
+        session.queue_message(message, self._on_update_checked)
+
+    def _on_update_checked(self, _session, message):
+        now = datetime.now()
+        app.config.set('last_update_check', now.strftime('%Y-%m-%d %H:%M'))
+
+        body = message.props.response_body.data
+        if not body:
+            log.warning('Could not reach gajim.org for update check')
+            return
+
+        data = json.loads(body)
+        latest_version = data['current_version']
+
+        if V(latest_version) > V(app.version):
+            def _on_cancel(is_checked):
+                if is_checked:
+                    app.config.set('check_for_update', False)
+
+            def _on_update(is_checked):
+                if is_checked:
+                    app.config.set('check_for_update', False)
+                helpers.open_uri('https://gajim.org/download')
+
+            NewConfirmationCheckDialog(
+                _('Update Available'),
+                _('Gajim Update Available'),
+                _('There is an update available for Gajim '
+                  '(latest version: %s)' % str(latest_version)),
+                _('_Do not show again'),
+                [DialogButton.make('Cancel',
+                                    text=_('_Later'),
+                                    callback=_on_cancel),
+                 DialogButton.make('Accept',
+                                    text=_('_Update Now'),
+                                    callback=_on_update)]).show()
+        else:
+            log.info('Gajim is up to date')
+
     def run(self, application):
         if app.config.get('trayicon') != 'never':
             self.show_systray()
@@ -1997,6 +2077,8 @@ def __init__(self):
         if sys.platform not in ('win32', 'darwin'):
             logind.enable()
             music_track.enable()
+        else:
+            GLib.timeout_add_seconds(20, self.check_for_updates)
 
         idle.Monitor.set_interval(app.config.get('autoawaytime') * 60,
                                   app.config.get('autoxatime') * 60)